Compare commits

..

50 Commits

Author SHA1 Message Date
Florian Müllner
8b087cfe56 Bump version to 3.34.2
Update NEWS.
2019-12-11 20:05:26 +01:00
Bruce Cowan
c05328f76a Update British English translation 2019-12-11 10:25:27 +00:00
Tim Crawford
868a617907 backends/native: Fix double free of error
error is an autoptr, so must not be explicitly freed.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1852
Fixes: 5c500ad402 ("backend: Move GPU ownership from the monitor manager to the backend")

https://gitlab.gnome.org/GNOME/mutter/merge_requests/960


(cherry picked from commit d70ddc65ea)
2019-12-06 19:56:51 +00:00
Pekka Paalanen
6f02d2ead0 kms-impl/simple: Fix meta_set_fallback_feedback_idle
Presumably this function is supposed to be like
meta_kms_impl_simple_handle_page_flip_callback() but the condition in the
if-statement is inverted. Fix the inversion to make these two functions look
alike.

This is part 2 of 2 fixing a complete desktop freeze when drmModePageFlip()
fails with EINVAL and the fallback to drmModeSetCrtc() succeeds but the success
is not registered correctly as completed "flip". The freeze occurs under
wait_for_pending_flips() which calls down into meta_kms_impl_device_dispatch()
which ends up poll()'ing the DRM fd even though drmModeSetCrtc() will not
produce a DRM event, hence the poll() never returns. The freeze was observed
when hotplugging a DisplayLink dock for the first time on Ubuntu 19.10.

This patch makes meta_set_fallback_feedback_idle() actually end up calling into
notify_view_crtc_presented() which decrements
secondary_gpu_state->pending_flips so that wait_for_pending_flips() can finish.

CC stable: gnome-3-34

https://gitlab.gnome.org/GNOME/mutter/merge_requests/953
(cherry picked from commit 832a522cce)
2019-12-06 17:27:15 +01:00
Pekka Paalanen
fc77efbcd7 kms: Process impl idle callbacks before pre dispatch flush
mode_set_fallback() schedules a call to mode_set_fallback_feedback_idle(), but
it is possible for Mutter to repaint before the idle callbacks are dispatched.
If that happens, mode_set_fallback_feedback_idle() does not get called before
Mutter enters wait_for_pending_flips(), leading to a deadlock.

Add the needed interfaces so that meta_kms_device_dispatch_sync() can flush all
the implementation idle callbacks before it checks if any "events" are
available. This prevents the deadlock by ensuring
mode_set_fallback_feedback_idle() does get called before potentially waiting
for actual DRM events.

Presumably this call would not be needed if the implementation was running in
its own thread, since it would eventually dispatch its idle callbacks before
going to sleep polling on the DRM fd. This call might even be unnecessary
overhead in that case, synchronizing with the implementation thread needlessly.
But the thread does not exist yet, so this is needed for now.

This is part 1 of 2 fixing a complete desktop freeze when drmModePageFlip()
fails with EINVAL and the fallback to drmModeSetCrtc() succeeds but the success
is not registered correctly as completed "flip". The freeze occurs under
wait_for_pending_flips() which calls down into meta_kms_impl_device_dispatch()
which ends up poll()'ing the DRM fd even though drmModeSetCrtc() will not
produce a DRM event, hence the poll() never returns. The freeze was observed
when hotplugging a DisplayLink dock for the first time on Ubuntu 19.10.

CC stable: gnome-3-34

https://gitlab.gnome.org/GNOME/mutter/merge_requests/953
(cherry picked from commit 79491df2b8)
2019-12-06 17:27:14 +01:00
Florian Müllner
c0e76186da stack: Allow promoting transient windows to their parent's layer
When a window that should be stacked above another one is placed in a lower
layer than the other window, we currently allow promoting it to the higher
layer when it has a "transient type". We should do the same when the window
is an actual transient of the other window.

This is particularly relevant for wayland windows, where types play a
much smaller role: Transient windows like non-modal dialogs (and since
commit 666bef7a, popup windows as well) currently end up underneath their
always-on-top parent.

https://gitlab.gnome.org/GNOME/mutter/issues/587


(cherry picked from commit 1c89fce30e)
2019-11-29 14:18:59 +00:00
Robert Mader
1b75d78c72 shaped-texture: Do not invalidate content on set_cogl_texture()
This was wrongly introduced in 75cffd0ec4. As the comment above explains, we
only want to queue redraws in response to surface/buffer damage.

This triggered a full redraw when using DMA buffers on Wayland as we currently
create a new texture on every buffer_attach(), breaking partial invalidation.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/947


(cherry picked from commit 0247d35e5a)
2019-11-26 22:43:54 +00:00
Jonas Dreßler
cbbffd1db7 cursor-tracker: Add API to keep the wayland pointer focus while hidden
Since commit a2a8f0cda we force the focus surface of the
meta-wayland-pointer to NULL while the pointer is invisible. This
introduced an issue with the a11y magnifier of the shell, which uses
`meta_cursor_tracker_set_pointer_visible` to hide the real cursor and
show its own magnified cursor at the correct position: Because the
meta-wayland-pointer is still used to communicate with Wayland clients,
the UI of the windows will not respond to mouse movement anymore as
soon as the real cursor is hidden.

Fix this issue for now by adding an additional method to the
cursor-tracker which allows disabling the behavior commit a2a8f0cda
introduced.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/832
2019-11-25 16:15:14 +01:00
Marco Trevisan (Treviño)
06202c342b device-manager-x11: Ignore events if no source device is set
There might be some inconsistent event for which we don't have a known
source device.

In the current state we don't handle them and we could crash when getting
the current device tool.

So, add an utility function that retrieves the source device for an event
that warns if no device is found, and use this for Motion, Key and Button
events.

In case we don't have a valid source in such case, just return early instead
of trying to generate invalid clutter events.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/823


(cherry picked from commit 427670cc63)
2019-11-23 01:47:33 +00:00
Robert Mader
9c372388da clutter/cally-root: Use g_clear_signal_handler and fix a signal leak
This commit was split out from `cleanup: Use g_clear_signal_handler()
where possible` as it fixes an actual signal leak and should therefore
get backported to stable releases.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/940
2019-11-21 16:22:14 +01:00
Carlos Garnacho
7e741fe2d2 wayland: Move "ownership" of the DnD selection source to the data device
On wl_data_source destruction we used to indirectly unset the DnD selection
owner via the wl_resource destructor triggering the destruction of the
MetaWaylandDataSource, which would be caught through the weak ref set by
the MetaWaylandDragGrab.

This works as long as the grab is held, however we have a window between
the button being released and the drop site replying with
wl_data_offer.finish that the MetaWaylandDataSource is alive, but its
destruction wouldn't result in the call chain above to unsetting the DnD
source.

In other selection sources, we let the MetaWaylandDataDevice hold the
"ownership" of the MetaWaylandDataSource, and its weak ref functions unset
the respective MetaSelection owners. Do the same here, so the
MetaWaylandDataSource destruction is listened for all its lifetime.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit e5af790acb)
2019-11-20 12:59:58 +01:00
Carlos Garnacho
edb618b2a4 wayland: Do not cancel data source on offer destruction
This is wrong for both clipboard and DnD, as the selection source
will still be able to focus another surface, and churn another
wl_offer.

We should just detach the data offer from the data source in this
case, and let the source live on. However, we should still check
that there is a source and an offer to finish DnD, do that when
handling the drop operation instead.

https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit 48639ac5da)
2019-11-20 12:59:40 +01:00
Carlos Garnacho
e2d6b33b61 wayland: Avoid redundant cancel() call
This is unnecessary as we are unsetting the DnD selection owner,
and will result in the related data source being cancelled already.

https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit e7b2f9603e)
2019-11-20 12:59:19 +01:00
Carlos Garnacho
eac37b17b0 wayland: Drop unused wl_signal structs
Those were used to signal clipboard ownership around, but that got
replaced by MetaSelection and friends. These signals are no longer
listened on, so can be safely removed.

https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit 46b3811e22)
2019-11-20 12:58:30 +01:00
Hans de Goede
d78585d68a cursor-renderer/native: Fix cursor drawing in combination with panel_orientation_transform
Properly take the panel_orientation_transform into account in
update_monitor_crtc_cursor. This fixes us sometimes drawing the cursor
on two monitors at the same time as we did not properly swap the crtc
width/height when a panel_orientation_transform is active.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/927


(cherry picked from commit 8907a29912)
2019-11-13 10:35:31 +00:00
Hans de Goede
c462544f78 output-kms: Fix "panel orientation" kms-prop being ignored on native outputs
Actually store the panel_orientation_transform in the meta_output, so
that it gets honored by the core code.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/927


(cherry picked from commit a5f986259f)
2019-11-13 10:35:04 +00:00
Carlos Garnacho
eb78b7d0d1 compositor: Plug cairo_region_t leak
The MetaBackgroundActor uses a region to find out the areas that need
repainting, but forgot to free it, oops.

(cherry-picked from 40e6aa7d94)

https://gitlab.gnome.org/GNOME/mutter/merge_requests/873
2019-11-12 13:37:30 +01:00
Carlos Garnacho
cc00e55513 backends: Plug MetaKmsPageFlipData leak
If the page flip is postponed, keep a ref to it, but still unref it
on the page flip callback anyways. Fix suggested by Jonas Ådahl.

(cherry-picked from 668be1f4bd)

https://gitlab.gnome.org/GNOME/mutter/merge_requests/873
2019-11-12 13:37:30 +01:00
Hans de Goede
a14e7b441c input-settings/x11: Add missing clutter_x11_trap_x_errors around XIGetProperty
Add missing clutter_x11_[un]trap_x_errors around the XIGetProperty call
in meta-input-settings-x11.c's get_property helper function.

This fixes mutter crashing with the following error if the XInput device
goes away at an unconvenient time:

 X Error of failed request:  XI_BadDevice (invalid Device parameter)
   Major opcode of failed request:  131 (XInputExtension)
   Minor opcode of failed request:  59 ()
   Device id in failed request: 0x200011
   Serial number of failed request:  454
   Current serial number in output stream:  454

https://gitlab.gnome.org/GNOME/mutter/merge_requests/928
2019-11-10 22:42:44 +01:00
Robert Mader
403d8fcc66 plugin-manager: Kill window effects on destroy
We do so for all other window effects already. Why this was left out
is unknown (9b3a0d1ad8), but we will need it for a fix in GS.

Related: https://gitlab.gnome.org/GNOME/mutter/issues/655

https://gitlab.gnome.org/GNOME/mutter/merge_requests/924


(cherry picked from commit a4f51da184)
2019-11-08 22:44:34 +00:00
Florian Müllner
7e5366f233 plugins/default: Handle skipped animations
We currently assume that the actor_animate() helper function returns
a timeline. However Clutter may skip implicit animations and simple
set properties directly, for example when the actor is hidden.

The returned timeline will be NULL in that case, and we abort when
using it as instance parameter to g_signal_connect().

Fix this by only setting up a completed handler when we are actually
animating, and complete the effect directly otherwise.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/925
2019-11-08 19:19:45 -03:00
Xiang Fan
cf78598974 wayland/surface: Don't double scale when getting absolute coordinates
The actor is already in surface coordinate space, so we should not scale
with the buffer scale to transform surface coordinates to stage
coordinates.

This bug causes input method using wayland text-input protocol to
receive wrong cursor location. Reproduced in ibus (when candidate
window is open) with scaling factor other than 1.

This commit also fixes pointer confinement.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/915
2019-11-07 17:56:14 +01:00
Marco Trevisan (Treviño)
7c1f3498fe window-props: Don't set override redirect windows as top-level parent
Java applications might use override-redirect windows as parent windows for
top-level windows, although this is not following the standard [1].

In such case, the first non-override-redirect child window that is created
was marked as being on_all_workspaces since the call to
should_be_on_all_workspaces() returns TRUE for its parent, and this even
though the on_all_workspaces_requested bit is unset.
When a further child of this window was added, it was set as not having a
workspace and not being on_all_workspaces, since the call to
should_be_on_all_workspaces() for its parent would return FALSE (unless if
it is in a different monitor, and the multiple-monitors workspaces are
disabled).

Since per commit 09bab98b we don't recompute the workspace if the
on_all_workspaces bit is unset, we could end up in a case where a window can
be nor in all the workspaces or in a specific workspace.

So let's just ignore the transient_for bit for a window if that points to an
override-redirect, using the x11 root window instead.

Add a stacking test to verify this scenario (was failing before of this
commit).

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/885
https://gitlab.gnome.org/GNOME/mutter/merge_requests/895

[1] https://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472512128


(cherry picked from commit bacbbbd628)
2019-11-07 16:21:37 +00:00
Marco Trevisan (Treviño)
598be2b1d8 window-props: Don't look for parent multiple times
Once we set the transient_for, we look for parent MetaWindow, so instead
of overwriting this value for loops check, just use another function
and avoid to look for the xwindow again when setting the MetaWindow parent.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/895


(cherry picked from commit c85fb107c0)
2019-11-07 16:21:09 +00:00
Marco Trevisan (Treviño)
a8776a9634 window: Assert we only set a NULL workspace when unmanaging
There might be cases in which a window might be marked as both not in all
workspaces and with NULL workspace.

So to avoid this to happen, let's just assert early instead of doing this at
later point where the context might not be clear.

Related to https://gitlab.gnome.org/GNOME/mutter/issues/885

https://gitlab.gnome.org/GNOME/mutter/merge_requests/895


(cherry picked from commit 13f10e36e4)
2019-11-07 16:19:25 +00:00
Marco Trevisan (Treviño)
4b238c10f4 window: Warn if O-R window workspace state is used
Override-redirect windows have no workspace by default, and can't be parent
of a top-level window, so we must check that the parent window is not an
O-R one when setting the workspace state.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/895


(cherry picked from commit 2644e54c51)
2019-11-07 16:18:55 +00:00
Jonas Ådahl
6fa860481c wayland/actor-surface: Always store away frame callbacks on commit
We're expected by MetaWaylandSurface to always pick the frame callbacks
out from the pending state when committing (applying) so that no frame
callbacks are unaccounted for. We failed to do this if our actor for
some reason (e.g. associated window was unmanaged) was destroyed. To
handle this situation better, store away the frame callbacks until we
some later point in time need to pass them on forward.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/893


(cherry picked from commit 0e5a5df5fe)
2019-11-07 13:51:43 +00:00
Florian Müllner
4ba3c4537e ci: Fix checking out gnome-shell on stable branches
For stable branches, we currently only check out the correct shell
branch for merge requests. For the regular pipeline, our code to
determine the current mutter branch fails because CI runs on a
temporary "pipeline/12345" branch that doesn't exist for gnome-shell.

Switching to the correct gitlab environment variable fixes that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/811
2019-11-07 00:14:41 +01:00
Marco Trevisan (Treviño)
1f56514e40 x11-display: Don't unset the X11 focused window after setting one
When using DesktopIcons extension and clicking in an icon, gnome-shell
starts an infinite loop caused by the first focus change that may trigger
on X11 a focus in/out event that leads to stage activation/deactivation
which never ends.

This happens because as part of meta_x11_display_set_input_focus_xwindow()
to focus the X11 stage window, we unset the display focus, but this also
causes to request the X11 display to unset the focus since we convolute by
calling meta_x11_display_set_input_focus() with no window, that leads to
focusing the no_focus_window and then a focus-in / focus-out dance that the
shell amplifies in order to give back the focus to the stage.

In order to fix this, mimic what meta_display_set_input_focus() does, but
without updating the X11 display, and so without implicitly calling
meta_x11_display_set_input_focus(), stopping the said convolution and
properly focusing the requested xwindow.
Also ensure that we're not doing this when using an older timestamp, since
this check isn't performed anymore.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/896
Fixes https://gitlab.gnome.org/GNOME/mutter/issues/899

https://gitlab.gnome.org/GNOME/mutter/merge_requests/909


(cherry picked from commit efe5bed5b4)
2019-11-06 17:48:19 +00:00
Jonas Ådahl
5e1bbb770e tests/monitor-unit-tests: Add another tiling window hot plug test
Checks that we handle hot plugs of a untiled window, that was previously
tiled.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:26 -03:00
Jonas Ådahl
3df4348f23 window: Reset tile monitor number when untiling
Otherwise we'll end up trying to access the out of date state later.

Fixes the following test failure backtrace:

    #0  _g_log_abort ()
    #1  g_logv ()
    #2  g_log ()
    #3  meta_monitor_manager_get_logical_monitor_from_number ()
    #4  meta_window_get_work_area_for_monitor ()
    #5  meta_window_get_tile_area ()
    #6  constrain_maximization ()
    #7  do_all_constraints ()
    #8  meta_window_constrain ()
    #9  meta_window_move_resize_internal ()
    #10 meta_window_tile ()

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:25 -03:00
Jonas Ådahl
9ed33dc72e tests/monitor-unit-tests: Add window tiling hot plug test
This test that we handle hot plugs correctly together with tiled
windows.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:23 -03:00
Jonas Ådahl
8cb0646b62 tests/runner: Move window shown synchronization to helper
https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:22 -03:00
Jonas Ådahl
c9a05d4581 tests/monitor-unit-tests: Move test client sanity check into helper
https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:21 -03:00
Jonas Ådahl
98a1630fa2 window: Always update tile monitor number on hot plug
Otherwise we'll end up crashing if we had two connected monitors,
unplugged both, then replugged in a single one.

Avoids the following error:

    #0  _g_log_abort ()
    #1  g_logv ()
    #2  g_log ()
    #3  meta_monitor_manager_get_logical_monitor_from_number ()
    #4  meta_window_get_work_area_for_monitor ()
    #5  meta_window_get_tile_area ()
    #6  constrain_maximization ()
    #7  do_all_constraints ()
    #8  meta_window_constrain ()
    #9  meta_window_move_resize_internal ()
    #10 meta_window_move_resize_frame ()
    #11 meta_window_move_resize_now ()
    #12 idle_move_resize ()
    #13 call_idle_later ()

https://bugzilla.redhat.com/show_bug.cgi?id=1767703

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:20 -03:00
Jonas Ådahl
4c48c859ea plugins/default: Clean up tile preview when closing display
On finalize, the preview actor will have been destroyed behind our back;
avoid that by cleaning up before it's too late.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:19 -03:00
Jonas Ådahl
d7bdaeeb82 plugin/default: Init quark before using
Cut lines in pieces, and remove useless "optimizations" while at it

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:17 -03:00
Jonas Ådahl
3564b0df4a display: Add 'closing' signal
Emitted when the MetaDisplay is closing. Meant for clean up that depends
on things that will be torn down during closing.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:15 -03:00
Olivier Fourdan
34b5a07d58 renderer-native: Separate offscreen and shadowfb
Create the intermediate shadow framebuffer for use exclusively when a
shadowfb is required.

Keep the previous offscreen framebuffer is as an intermediate
framebuffer for transformations only.

This way, we can apply transformations between in-memory framebuffers
prior to blit the result to screen, and achieve acceptable performance
even with software rendering on discrete GPU.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/917

(cherry picked from commit 551641c74822ca2e3c685e49603836ebf5397df2)
2019-11-04 11:08:02 +01:00
Olivier Fourdan
a112d7a10e clutter/stage-view: Separate offscreen and shadowfb
Previously, we would use a single offscreen framebuffer for both
transformations and when a shadow framebuffer should be used, but that
can be dreadfully slow when using software rendering with a discrete GPU
due to bandwidth limitations.

Keep the offscreen framebuffer for transformations only and add another
intermediate shadow framebuffer used as a copy of the onscreen
framebuffer.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/917

(cherry picked from commit 2b8b450fe16c21f0f37a1779560c0e5da61a9b89)
2019-11-04 11:08:02 +01:00
Carlos Garnacho
51f7e8c4dd wayland: Check stylus serials on meta_wayland_seat_can_popup()
This allows xdg_popup.grab() to work with styli. Without this check
we would bail out and emit xdg_popup.popup_done, leaving stylus users
unable to interact with popup menus, comboboxes, etc...

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/886
2019-10-30 10:08:51 +01:00
Jonas Ådahl
f4574ea36f x11: Limit touch replay pointer events to when replaying
When a touch sequence was rejected, the emulated pointer events would be
replayed with old timestamps. This caused issues with grabs as they
would be ignored due to being too old. This was mitigated by making sure
device event timestamps never travelled back in time by tampering with
any event that had a timestamp seemingly in the past.

This failed when the most recent timestamp that had been received were
much older than the timestamp of the new event. This could for example
happen when a session was left not interacted with for 40+ days or so;
when interacted with again, as any new timestamp would according to
XSERVER_TIME_IS_BEFORE() still be in the past compared to the "most
recent" one. The effect is that we'd always use the `latest_evtime` for
all new device events without ever updating it.

The end result of this was that passive grabs would become active when
interacted with, but would then newer be released, as the timestamps to
XIAllowEvents() would out of date, resulting in the desktop effectively
freezing, as the Shell would have an active pointer grab.

To avoid the situation where we get stuck with an old `latest_evtime`
timestamp, limit the tampering with device event timestamp to 1) only
pointer events, and 2) only during the replay sequence. The second part
is implemented by sending an asynchronous message via the X server after
rejecting a touch sequence, only potentially tampering with the device
event timestamps until the reply. This should avoid the stuck timestamp
as in those situations, we'll always have a relatively up to date
`latest_evtime` meaning XSERVER_TIME_IS_BEFORE() will not get confused.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
2019-10-30 10:08:39 +01:00
Jonas Ådahl
2301cde8f7 display: Move finishing of touch sequence to the backend
We need to manipulate an X11 grab when a touch sequence ends; move that
logic to where it belongs - in the X11 backend.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
2019-10-30 10:08:32 +01:00
Carlos Garnacho
ef2f5f07f0 x11: Update X11 focus before updating MetaDisplay focus
In a similar vein to commit 8fd55fef85. This notably failed when setting
the focus on the stage (eg. to redirect key events to Clutter actors).
Deeper in MetaDisplay focus updating machinery, it would check
meta_stage_is_focused() which would still return FALSE at the time it's
called.

This would not typically have side effects, but our "App does not respond"
dialogs see the focus change under their feet, so they try to bring
themselves to focus again. This results in a feedback loop.

Changing the order results in later checks on the X11 POV of the focus
being correct, so focus is not mistakenly stolen from the close dialog,
and it actually succeeds in keeping the key focus.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1607

https://gitlab.gnome.org/GNOME/mutter/merge_requests/876


(cherry picked from commit 71c3f4af31)
2019-10-24 15:52:41 +00:00
Robert Mader
85f5db7e73 wayland/surface: Reset buffer_destroy_handler_id
Syncronized subsurfaces that call into `merge_pending_state` might
otherwise not create new destroy handlers, ending up with a invalid
handler ids, throwing errors and leaking.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/868


(cherry picked from commit 98892391d7)
2019-10-21 13:03:25 +00:00
Robert Mader
c0037305eb window-actor: Add a missing NULL-check
We shouldn't crash on a NULL-clip.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/856
2019-10-18 13:40:20 +02:00
Cosimo Cecchi
ff885fea31 monitor-manager: check for underscan setting validity upfront
Instead of doing a roundtrip to the X server before setting it, rely on
the previous value fetched before the configuration was sent over DBus.
This matches the argument check we already do elsewhere, and will allow
us to more easily add an additional condition to determine if underscan
is supported.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/673


(cherry picked from commit 8665084df1)
2019-10-18 11:36:34 +00:00
Marco Trevisan (Treviño)
bf17e04010 clutter/stage: Actually set key focus to an actor on key focus
As per commit c2d03bf73 we're using a private method to set the actors key
focus and emit key-focus-in signal, but we're using inverted logic here.

So flip the parameter to match the expected result.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/860


(cherry picked from commit 553211dd81)
2019-10-15 18:31:50 +00:00
Marco Trevisan (Treviño)
a22731e2b2 clutter/actor: Save key-focus state and unset it before destruction
When clutter actors with key focus are destroyed we emit ::key-focus-out on
them just after their destruction. This is against our assumption that no
signal should be emitted after "::destroy" (see GNOME/mutter!769 [1]), and
in fact could cause the shell to do actions that we won't ever stop on
destroy callback.

To avoid this to happen, use a private function to set its key-state (so we
can avoid looking for the stage) and emit ::key-focus-in/out events and use
this value in both clutter_actor_has_key_focus(),
clutter_actor_grab_key_focus() and on unmap and destruction to unset the
stage key focus before we emit the ::destroy signal.

As result of this, we can now avoid to unset the key focus on actor
destruction in the stage.

[1] https://gitlab.gnome.org/GNOME/mutter/merge_requests/769

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1704


(cherry picked from commit c2d03bf73e)
2019-10-15 10:42:55 +00:00
Niels De Graef
b6ed7d6781 dbus-session-watcher: Chain up to parent finalize()
https://gitlab.gnome.org/GNOME/mutter/merge_requests/847


(cherry picked from commit 3a688988e0)
2019-10-14 07:51:15 +00:00
263 changed files with 8899 additions and 3520 deletions

View File

@@ -18,7 +18,7 @@ RUN dnf -y update && dnf -y upgrade && \
dnf builddep -y mutter && \
# Until Fedora catches up with meson build-deps
dnf install -y meson xorg-x11-server-Xorg gnome-settings-daemon-devel egl-wayland-devel xorg-x11-server-Xwayland graphene-devel && \
dnf install -y meson xorg-x11-server-Xorg gnome-settings-daemon-devel egl-wayland-devel xorg-x11-server-Xwayland && \
# Until Fedora catches up with mesa bug fixes
dnf upgrade -y mesa-dri-drivers mesa-libEGL && \

View File

@@ -1,6 +1,5 @@
#!/usr/bin/bash
mutter_branch=$(git describe --contains --all HEAD)
gnome_shell_target=
git clone https://gitlab.gnome.org/GNOME/gnome-shell.git
@@ -26,8 +25,7 @@ if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
fi
if [ -z "$gnome_shell_target" ]; then
gnome_shell_target=$(git branch -r -l origin/$mutter_branch)
gnome_shell_target=${gnome_shell_target:-$(git branch -r -l ${mutter_branch#remotes/})}
gnome_shell_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
gnome_shell_target=${gnome_shell_target:-origin/master}
echo Using $gnome_shell_target instead
fi

37
NEWS
View File

@@ -1,18 +1,37 @@
3.35.1
3.34.2
======
* Fix immediate screen blank after releaseing inhibitor [Tim; #573]
* Respond to frame callbacks regardless of damage [Jonas; !839]
* selection [Carlos; !842]
* Fix Night Light on wayland [Jonas; !840]
* Fix immediate screen blank after releasing inhibitor [Tim; #573]
* Respond to frame callbacks regardless of damage [Jonas Å.; !839]
* Translate well-known selection atoms to mimetypes [Carlos; !842]
* Fix Night Light on wayland [Jonas Å.; !840]
* Fix various copy+paste/DND regressions [Carlos; !848, #789, #842,
#793, #845, #854]
* Misc. bug fixes and cleanups [Daniel, Marco, Jonas, Georges;
!841, !764, !837, !846]
* Don't emit focus event after desctruction [Marco; gnome-shell#1704, !860]
* Fix hang when opening not-responding dialog on Xorg [Carlos; !876]
* Fix frozen grabs on Xorg after weeks of inactivity [Jonas Å.; !886]
* Fix triggering popups from stylus devices on wayland [Carlos; #886]
* Support shadow framebuffers for offscreen rendering [Olivier; !917]
* Fix hang after interacting with desktop icons on X11 [Marco; !909]
* Don't double scale when getting absolute surface coordinates [Xiang; !915]
* Kill window effects on destroy [Robert; !924]
* Use partial damage for dma-buf and EGLImage buffers on wayland [Robert; #947]
* Do not stack transients underneath their always-on-top parent [Florian; #587]
* Fix KMS freeze after pageflip [Pekka; !953]
* Fixed crashes [Robert, Jonas Å., Marco, Hans, Carlos, Tim; !856, !912, !895,
!928, #591, !823, !960]
* Plugged memory leaks [Niels, Robert, Carlos; !847, !868, !873]
* Misc. bug fixes and cleanups [Daniel, Marco, Jonas Å., Georges, Cosimo,
Florian, Hans, Robert, Jonas D.; !841, !764, !837, !846, !673, !811, !893,
!925, !927, !940, !832]
Contributors:
Marco Trevisan (Treviño), Carlos Garnacho, Tim Klocke,
Georges Basile Stavracas Neto, Daniel van Vugt, Jonas Ådahl
Marco Trevisan (Treviño), Cosimo Cecchi, Tim Crawford, Jonas Dreßler,
Xiang Fan, Olivier Fourdan, Carlos Garnacho, Hans de Goede, Niels De Graef,
Tim Klocke, Robert Mader, Florian Müllner, Georges Basile Stavracas Neto,
Pekka Paalanen, Daniel van Vugt, Jonas Ådahl
Translators:
Bruce Cowan [en_GB]
3.34.1
======
* Fix startup of X11 session services on wayland [Carlos; #771]

View File

@@ -657,7 +657,7 @@ cally_actor_get_extents (AtkComponent *component,
ClutterActor *actor = NULL;
gint top_level_x, top_level_y;
gfloat f_width, f_height;
graphene_point3d_t verts[4];
ClutterVertex verts[4];
ClutterActor *stage = NULL;
g_return_if_fail (CALLY_IS_ACTOR (component));

View File

@@ -75,8 +75,8 @@ struct _CallyRootPrivate
GSList *stage_list;
/* signals id */
guint stage_added_id;
guint stage_removed_id;
gulong stage_added_id;
gulong stage_removed_id;
};
G_DEFINE_TYPE_WITH_PRIVATE (CallyRoot, cally_root, ATK_TYPE_GOBJECT_ACCESSIBLE)
@@ -149,11 +149,9 @@ cally_root_finalize (GObject *object)
stage_manager = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (root));
g_signal_handler_disconnect (stage_manager,
root->priv->stage_added_id);
g_clear_signal_handler (&root->priv->stage_added_id, stage_manager);
g_signal_handler_disconnect (stage_manager,
root->priv->stage_added_id);
g_clear_signal_handler (&root->priv->stage_removed_id, stage_manager);
G_OBJECT_CLASS (cally_root_parent_class)->finalize (object);
}

View File

@@ -1438,7 +1438,7 @@ static void cally_text_get_character_extents (AtkText *text,
PangoLayout *layout;
PangoRectangle extents;
const gchar *text_value;
graphene_point3d_t verts[4];
ClutterVertex verts[4];
actor = CALLY_GET_CLUTTER_ACTOR (text);
if (actor == NULL) /* State is defunct */
@@ -2294,7 +2294,7 @@ _cally_misc_get_index_at_point (ClutterText *clutter_text,
gint index, x_window, y_window, x_toplevel, y_toplevel;
gint x_temp, y_temp;
gboolean ret;
graphene_point3d_t verts[4];
ClutterVertex verts[4];
PangoLayout *layout;
gint x_layout, y_layout;

View File

@@ -340,7 +340,7 @@ clutter_actor_box_contains (const ClutterActorBox *box,
/**
* clutter_actor_box_from_vertices:
* @box: a #ClutterActorBox
* @verts: (array fixed-size=4): array of four #graphene_point3d_t
* @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().
@@ -348,8 +348,8 @@ clutter_actor_box_contains (const ClutterActorBox *box,
* Since: 1.0
*/
void
clutter_actor_box_from_vertices (ClutterActorBox *box,
const graphene_point3d_t verts[])
clutter_actor_box_from_vertices (ClutterActorBox *box,
const ClutterVertex verts[])
{
gfloat x_1, x_2, y_1, y_2;

View File

@@ -135,7 +135,7 @@ struct _AnchorCoord
} fraction;
/* Use when is_fractional == FALSE */
graphene_point3d_t units;
ClutterVertex units;
} v;
};
@@ -163,7 +163,7 @@ struct _SizeRequest
struct _ClutterLayoutInfo
{
/* fixed position coordinates */
graphene_point_t fixed_pos;
ClutterPoint fixed_pos;
ClutterMargin margin;
@@ -173,8 +173,8 @@ struct _ClutterLayoutInfo
guint x_expand : 1;
guint y_expand : 1;
graphene_size_t minimum;
graphene_size_t natural;
ClutterSize minimum;
ClutterSize natural;
};
const ClutterLayoutInfo * _clutter_actor_get_layout_info_or_defaults (ClutterActor *self);
@@ -203,13 +203,13 @@ struct _ClutterTransformInfo
AnchorCoord anchor;
/* translation */
graphene_point3d_t translation;
ClutterVertex translation;
/* z_position */
gfloat z_position;
/* transformation center */
graphene_point_t pivot;
ClutterPoint pivot;
gfloat pivot_z;
CoglMatrix transform;

View File

@@ -701,7 +701,7 @@ struct _ClutterActorPrivate
ClutterAllocationFlags allocation_flags;
/* clip, in actor coordinates */
graphene_rect_t clip;
ClutterRect clip;
/* the cached transformation matrix; see apply_transform() */
CoglMatrix transform;
@@ -746,6 +746,9 @@ struct _ClutterActorPrivate
*/
ClutterTextDirection text_direction;
/* a counter used to toggle the CLUTTER_INTERNAL_CHILD flag */
gint internal_child;
/* meta classes */
ClutterMetaGroup *actions;
ClutterMetaGroup *constraints;
@@ -902,6 +905,7 @@ enum
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,
@@ -1288,7 +1292,7 @@ static gboolean
_clutter_actor_transform_local_box_to_stage (ClutterActor *self,
ClutterStage *stage,
const ClutterActorBox *box,
graphene_point_t vertices[4])
ClutterPoint vertices[4])
{
CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
CoglMatrix stage_transform, inv_stage_transform;
@@ -1344,7 +1348,7 @@ clutter_actor_pick_box (ClutterActor *self,
const ClutterActorBox *box)
{
ClutterStage *stage;
graphene_point_t vertices[4];
ClutterPoint vertices[4];
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (box != NULL);
@@ -1363,7 +1367,7 @@ _clutter_actor_push_pick_clip (ClutterActor *self,
const ClutterActorBox *clip)
{
ClutterStage *stage;
graphene_point_t vertices[4];
ClutterPoint vertices[4];
stage = CLUTTER_STAGE (_clutter_actor_get_stage_internal (self));
@@ -2345,7 +2349,8 @@ _clutter_actor_rerealize (ClutterActor *self,
}
static void
clutter_actor_real_pick (ClutterActor *self)
clutter_actor_real_pick (ClutterActor *self,
const ClutterColor *color)
{
if (clutter_actor_should_pick_paint (self))
{
@@ -2889,8 +2894,8 @@ clutter_actor_real_queue_relayout (ClutterActor *self)
* @self: A #ClutterActor
* @ancestor: (allow-none): A #ClutterActor ancestor, or %NULL to use the
* default #ClutterStage
* @point: A point as #graphene_point3d_t
* @vertex: (out caller-allocates): The translated #graphene_point3d_t
* @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
@@ -2904,10 +2909,10 @@ clutter_actor_real_queue_relayout (ClutterActor *self)
* Since: 0.6
*/
void
clutter_actor_apply_relative_transform_to_point (ClutterActor *self,
ClutterActor *ancestor,
const graphene_point3d_t *point,
graphene_point3d_t *vertex)
clutter_actor_apply_relative_transform_to_point (ClutterActor *self,
ClutterActor *ancestor,
const ClutterVertex *point,
ClutterVertex *vertex)
{
gfloat w;
CoglMatrix matrix;
@@ -2934,10 +2939,10 @@ clutter_actor_apply_relative_transform_to_point (ClutterActor *self,
}
static gboolean
_clutter_actor_fully_transform_vertices (ClutterActor *self,
const graphene_point3d_t *vertices_in,
graphene_point3d_t *vertices_out,
int n_vertices)
_clutter_actor_fully_transform_vertices (ClutterActor *self,
const ClutterVertex *vertices_in,
ClutterVertex *vertices_out,
int n_vertices)
{
ClutterActor *stage;
CoglMatrix modelview;
@@ -2979,8 +2984,8 @@ _clutter_actor_fully_transform_vertices (ClutterActor *self,
/**
* clutter_actor_apply_transform_to_point:
* @self: A #ClutterActor
* @point: A point as #graphene_point3d_t
* @vertex: (out caller-allocates): The translated #graphene_point3d_t
* @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
@@ -2989,9 +2994,9 @@ _clutter_actor_fully_transform_vertices (ClutterActor *self,
* Since: 0.4
**/
void
clutter_actor_apply_transform_to_point (ClutterActor *self,
const graphene_point3d_t *point,
graphene_point3d_t *vertex)
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);
@@ -3041,10 +3046,10 @@ _clutter_actor_get_relative_transformation_matrix (ClutterActor *self,
* transformed vertices to @verts[]. */
static gboolean
_clutter_actor_transform_and_project_box (ClutterActor *self,
const ClutterActorBox *box,
graphene_point3d_t *verts)
const ClutterActorBox *box,
ClutterVertex verts[])
{
graphene_point3d_t box_vertices[4];
ClutterVertex box_vertices[4];
box_vertices[0].x = box->x1;
box_vertices[0].y = box->y1;
@@ -3068,8 +3073,8 @@ _clutter_actor_transform_and_project_box (ClutterActor *self,
* @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): return
* location for an array of 4 #graphene_point3d_t in which to store the result
* @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
@@ -3088,13 +3093,13 @@ _clutter_actor_transform_and_project_box (ClutterActor *self,
* Since: 0.6
*/
void
clutter_actor_get_allocation_vertices (ClutterActor *self,
ClutterActor *ancestor,
graphene_point3d_t *verts)
clutter_actor_get_allocation_vertices (ClutterActor *self,
ClutterActor *ancestor,
ClutterVertex verts[])
{
ClutterActorPrivate *priv;
ClutterActorBox box;
graphene_point3d_t vertices[4];
ClutterVertex vertices[4];
CoglMatrix modelview;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
@@ -3146,9 +3151,9 @@ clutter_actor_get_allocation_vertices (ClutterActor *self,
cogl_matrix_transform_points (&modelview,
3,
sizeof (graphene_point3d_t),
sizeof (ClutterVertex),
vertices,
sizeof (graphene_point3d_t),
sizeof (ClutterVertex),
vertices,
4);
}
@@ -3157,7 +3162,7 @@ clutter_actor_get_allocation_vertices (ClutterActor *self,
* clutter_actor_get_abs_allocation_vertices:
* @self: A #ClutterActor
* @verts: (out) (array fixed-size=4): Pointer to a location of an array
* of 4 #graphene_point3d_t where to store the result.
* 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
@@ -3171,8 +3176,8 @@ clutter_actor_get_allocation_vertices (ClutterActor *self,
* Since: 0.4
*/
void
clutter_actor_get_abs_allocation_vertices (ClutterActor *self,
graphene_point3d_t *verts)
clutter_actor_get_abs_allocation_vertices (ClutterActor *self,
ClutterVertex verts[])
{
ClutterActorPrivate *priv;
ClutterActorBox actor_space_allocation;
@@ -3413,7 +3418,7 @@ _clutter_actor_draw_paint_volume_full (ClutterActor *self,
{
static CoglPipeline *outline = NULL;
CoglPrimitive *prim;
graphene_point3d_t line_ends[12 * 2];
ClutterVertex line_ends[12 * 2];
int n_vertices;
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
@@ -4162,15 +4167,22 @@ clutter_actor_continue_paint (ClutterActor *self)
}
else
{
ClutterColor col = { 0, };
/* The actor will log a silhouette of itself to the stage pick log.
* Note that the picking color is no longer used as the "log" instead
* keeps a weak pointer to the actor itself. But we keep the color
* parameter for now so as to maintain ABI compatibility. The color
* parameter can be removed when someone feels like breaking the ABI
* along with gnome-shell.
*
* XXX:2.0 - Call the pick() virtual directly
*/
if (g_signal_has_handler_pending (self, actor_signals[PICK],
0, TRUE))
g_signal_emit (self, actor_signals[PICK], 0);
g_signal_emit (self, actor_signals[PICK], 0, &col);
else
CLUTTER_ACTOR_GET_CLASS (self)->pick (self);
CLUTTER_ACTOR_GET_CLASS (self)->pick (self, &col);
}
}
else
@@ -4465,11 +4477,11 @@ static const ClutterTransformInfo default_transform_info = {
{ 0, }, /* anchor XXX:2.0 - remove*/
GRAPHENE_POINT3D_INIT_ZERO, /* translation */
CLUTTER_VERTEX_INIT_ZERO, /* translation */
0.f, /* z-position */
GRAPHENE_POINT_INIT_ZERO, /* pivot */
CLUTTER_POINT_INIT_ZERO, /* pivot */
0.f, /* pivot-z */
CLUTTER_MATRIX_INIT_IDENTITY,
@@ -4548,8 +4560,8 @@ _clutter_actor_get_transform_info (ClutterActor *self)
}
static inline void
clutter_actor_set_pivot_point_internal (ClutterActor *self,
const graphene_point_t *pivot)
clutter_actor_set_pivot_point_internal (ClutterActor *self,
const ClutterPoint *pivot)
{
ClutterTransformInfo *info;
@@ -4854,11 +4866,11 @@ clutter_actor_get_rotation_angle (ClutterActor *self,
* rotation angle.
*/
static inline void
clutter_actor_set_rotation_center_internal (ClutterActor *self,
ClutterRotateAxis axis,
const graphene_point3d_t *center)
clutter_actor_set_rotation_center_internal (ClutterActor *self,
ClutterRotateAxis axis,
const ClutterVertex *center)
{
graphene_point3d_t v = GRAPHENE_POINT3D_INIT_ZERO;
ClutterVertex v = CLUTTER_VERTEX_INIT_ZERO;
GObject *obj = G_OBJECT (self);
ClutterTransformInfo *info;
@@ -5085,8 +5097,8 @@ clutter_actor_set_anchor_coord (ClutterActor *self,
}
static void
clutter_actor_set_clip_rect (ClutterActor *self,
const graphene_rect_t *clip)
clutter_actor_set_clip_rect (ClutterActor *self,
const ClutterRect *clip)
{
ClutterActorPrivate *priv = self->priv;
GObject *obj = G_OBJECT (self);
@@ -5101,6 +5113,7 @@ clutter_actor_set_clip_rect (ClutterActor *self,
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]);
}
@@ -5126,7 +5139,7 @@ clutter_actor_set_property (GObject *object,
case PROP_POSITION:
{
const graphene_point_t *pos = g_value_get_boxed (value);
const ClutterPoint *pos = g_value_get_boxed (value);
if (pos != NULL)
clutter_actor_set_position (actor, pos->x, pos->y);
@@ -5145,7 +5158,7 @@ clutter_actor_set_property (GObject *object,
case PROP_SIZE:
{
const graphene_size_t *size = g_value_get_boxed (value);
const ClutterSize *size = g_value_get_boxed (value);
if (size != NULL)
clutter_actor_set_size (actor, size->width, size->height);
@@ -5231,10 +5244,10 @@ clutter_actor_set_property (GObject *object,
case PROP_PIVOT_POINT:
{
const graphene_point_t *pivot = g_value_get_boxed (value);
const ClutterPoint *pivot = g_value_get_boxed (value);
if (pivot == NULL)
pivot = graphene_point_zero ();
pivot = clutter_point_zero ();
clutter_actor_set_pivot_point (actor, pivot->x, pivot->y);
}
@@ -5288,6 +5301,16 @@ clutter_actor_set_property (GObject *object,
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;
@@ -5480,11 +5503,11 @@ clutter_actor_get_property (GObject *object,
case PROP_POSITION:
{
graphene_point_t position;
ClutterPoint position;
graphene_point_init (&position,
clutter_actor_get_x (actor),
clutter_actor_get_y (actor));
clutter_point_init (&position,
clutter_actor_get_x (actor),
clutter_actor_get_y (actor));
g_value_set_boxed (value, &position);
}
break;
@@ -5499,11 +5522,11 @@ clutter_actor_get_property (GObject *object,
case PROP_SIZE:
{
graphene_size_t size;
ClutterSize size;
graphene_size_init (&size,
clutter_actor_get_width (actor),
clutter_actor_get_height (actor));
clutter_size_init (&size,
clutter_actor_get_width (actor),
clutter_actor_get_height (actor));
g_value_set_boxed (value, &size);
}
break;
@@ -5626,6 +5649,19 @@ clutter_actor_get_property (GObject *object,
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;
@@ -5773,7 +5809,7 @@ clutter_actor_get_property (GObject *object,
case PROP_ROTATION_CENTER_X: /* XXX:2.0 - remove */
{
graphene_point3d_t center;
ClutterVertex center;
clutter_actor_get_rotation (actor, CLUTTER_X_AXIS,
&center.x,
@@ -5786,7 +5822,7 @@ clutter_actor_get_property (GObject *object,
case PROP_ROTATION_CENTER_Y: /* XXX:2.0 - remove */
{
graphene_point3d_t center;
ClutterVertex center;
clutter_actor_get_rotation (actor, CLUTTER_Y_AXIS,
&center.x,
@@ -5799,7 +5835,7 @@ clutter_actor_get_property (GObject *object,
case PROP_ROTATION_CENTER_Z: /* XXX:2.0 - remove */
{
graphene_point3d_t center;
ClutterVertex center;
clutter_actor_get_rotation (actor, CLUTTER_Z_AXIS,
&center.x,
@@ -6044,7 +6080,18 @@ clutter_actor_dispose (GObject *object)
if (priv->parent != NULL)
{
ClutterActor *parent = priv->parent;
clutter_container_remove_actor (CLUTTER_CONTAINER (parent), self);
/* 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 */
@@ -6216,7 +6263,7 @@ clutter_actor_update_default_paint_volume (ClutterActor *self,
priv->clip.size.width >= 0 &&
priv->clip.size.height >= 0)
{
graphene_point3d_t origin;
ClutterVertex origin;
origin.x = priv->clip.origin.x;
origin.y = priv->clip.origin.y;
@@ -6492,7 +6539,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
g_param_spec_boxed ("position",
P_("Position"),
P_("The position of the origin of the actor"),
GRAPHENE_TYPE_POINT,
CLUTTER_TYPE_POINT,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
CLUTTER_PARAM_ANIMATABLE);
@@ -6551,7 +6598,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
g_param_spec_boxed ("size",
P_("Size"),
P_("The size of the actor"),
GRAPHENE_TYPE_SIZE,
CLUTTER_TYPE_SIZE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
CLUTTER_PARAM_ANIMATABLE);
@@ -6993,11 +7040,25 @@ clutter_actor_class_init (ClutterActorClass *klass)
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 #graphene_rect_t.
* expressed as a #ClutterRect.
*
* Setting this property to %NULL will unset the existing clip.
*
@@ -7010,7 +7071,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
g_param_spec_boxed ("clip-rect",
P_("Clip Rectangle"),
P_("The visible region of the actor"),
GRAPHENE_TYPE_RECT,
CLUTTER_TYPE_RECT,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
@@ -7047,7 +7108,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
g_param_spec_boxed ("pivot-point",
P_("Pivot Point"),
P_("The point around which the scaling and rotation occur"),
GRAPHENE_TYPE_POINT,
CLUTTER_TYPE_POINT,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
CLUTTER_PARAM_ANIMATABLE);
@@ -7269,7 +7330,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
g_param_spec_boxed ("rotation-center-x",
P_("Rotation Center X"),
P_("The rotation center on the X axis"),
GRAPHENE_TYPE_POINT3D,
CLUTTER_TYPE_VERTEX,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
G_PARAM_DEPRECATED);
@@ -7287,7 +7348,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
g_param_spec_boxed ("rotation-center-y",
P_("Rotation Center Y"),
P_("The rotation center on the Y axis"),
GRAPHENE_TYPE_POINT3D,
CLUTTER_TYPE_VERTEX,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
G_PARAM_DEPRECATED);
@@ -7305,7 +7366,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
g_param_spec_boxed ("rotation-center-z",
P_("Rotation Center Z"),
P_("The rotation center on the Z axis"),
GRAPHENE_TYPE_POINT3D,
CLUTTER_TYPE_VERTEX,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
G_PARAM_DEPRECATED);
@@ -8529,10 +8590,12 @@ clutter_actor_class_init (ClutterActorClass *klass)
/**
* 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.
@@ -8550,7 +8613,8 @@ clutter_actor_class_init (ClutterActorClass *klass)
G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED,
G_STRUCT_OFFSET (ClutterActorClass, pick),
NULL, NULL, NULL,
G_TYPE_NONE, 0);
G_TYPE_NONE, 1,
CLUTTER_TYPE_COLOR | G_SIGNAL_TYPE_STATIC_SCOPE);
/**
* ClutterActor::allocation-changed:
@@ -8957,7 +9021,7 @@ _clutter_actor_queue_redraw_full (ClutterActor *self,
if (flags & CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION)
{
ClutterActorBox allocation_clip;
graphene_point3d_t origin;
ClutterVertex origin;
/* If the actor doesn't have a valid allocation then we will
* queue a full stage redraw. */
@@ -9161,7 +9225,7 @@ clutter_actor_queue_redraw_with_clip (ClutterActor *self,
const cairo_rectangle_int_t *clip)
{
ClutterPaintVolume volume;
graphene_point3d_t origin;
ClutterVertex origin;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
@@ -10388,17 +10452,17 @@ clutter_actor_set_position (ClutterActor *self,
gfloat x,
gfloat y)
{
graphene_point_t new_position;
graphene_point_t cur_position;
ClutterPoint new_position;
ClutterPoint cur_position;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
graphene_point_init (&new_position, x, y);
clutter_point_init (&new_position, x, y);
cur_position.x = clutter_actor_get_x (self);
cur_position.y = clutter_actor_get_y (self);
if (!graphene_point_equal (&cur_position, &new_position))
if (!clutter_point_equals (&cur_position, &new_position))
_clutter_actor_create_transition (self, obj_props[PROP_POSITION],
&cur_position,
&new_position);
@@ -10833,8 +10897,8 @@ clutter_actor_set_height_internal (ClutterActor *self,
}
static void
clutter_actor_set_size_internal (ClutterActor *self,
const graphene_size_t *size)
clutter_actor_set_size_internal (ClutterActor *self,
const ClutterSize *size)
{
if (size != NULL)
{
@@ -10870,11 +10934,11 @@ clutter_actor_set_size (ClutterActor *self,
gfloat width,
gfloat height)
{
graphene_size_t new_size;
ClutterSize new_size;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
graphene_size_init (&new_size, width, height);
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
@@ -10893,11 +10957,11 @@ clutter_actor_set_size (ClutterActor *self,
}
else
{
graphene_size_t cur_size;
ClutterSize cur_size;
graphene_size_init (&cur_size,
clutter_actor_get_width (self),
clutter_actor_get_height (self));
clutter_size_init (&cur_size,
clutter_actor_get_width (self),
clutter_actor_get_height (self));
_clutter_actor_create_transition (self,
obj_props[PROP_SIZE],
@@ -10983,8 +11047,8 @@ clutter_actor_get_transformed_position (ClutterActor *self,
gfloat *x,
gfloat *y)
{
graphene_point3d_t v1;
graphene_point3d_t v2;
ClutterVertex v1;
ClutterVertex v2;
v1.x = v1.y = v1.z = 0;
clutter_actor_apply_transform_to_point (self, &v1, &v2);
@@ -11030,7 +11094,7 @@ clutter_actor_get_transformed_size (ClutterActor *self,
gfloat *height)
{
ClutterActorPrivate *priv;
graphene_point3d_t v[4];
ClutterVertex v[4];
gfloat x_min, x_max, y_min, y_max;
gint i;
@@ -11352,8 +11416,8 @@ clutter_actor_set_y_internal (ClutterActor *self,
}
static void
clutter_actor_set_position_internal (ClutterActor *self,
const graphene_point_t *position)
clutter_actor_set_position_internal (ClutterActor *self,
const ClutterPoint *position)
{
ClutterActorPrivate *priv = self->priv;
ClutterLayoutInfo *linfo;
@@ -11362,7 +11426,7 @@ clutter_actor_set_position_internal (ClutterActor *self,
linfo = _clutter_actor_get_layout_info (self);
if (priv->position_set &&
graphene_point_equal (position, &linfo->fixed_pos))
clutter_point_equals (position, &linfo->fixed_pos))
return;
clutter_actor_store_old_geometry (self, &old);
@@ -11447,7 +11511,8 @@ clutter_actor_set_y (ClutterActor *self,
* 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(), this function will return that coordinate.
* 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.
@@ -11494,7 +11559,8 @@ clutter_actor_get_x (ClutterActor *self)
* 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(), this function will return that coordinate.
* 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.
@@ -12179,7 +12245,7 @@ clutter_actor_set_pivot_point (ClutterActor *self,
gfloat pivot_x,
gfloat pivot_y)
{
graphene_point_t pivot = GRAPHENE_POINT_INIT (pivot_x, pivot_y);
ClutterPoint pivot = CLUTTER_POINT_INIT (pivot_x, pivot_y);
const ClutterTransformInfo *info;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
@@ -12340,7 +12406,7 @@ clutter_actor_set_rotation (ClutterActor *self,
gfloat y,
gfloat z)
{
graphene_point3d_t v;
ClutterVertex v;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
@@ -12537,6 +12603,7 @@ clutter_actor_set_clip (ClutterActor *self,
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]);
}
@@ -13039,6 +13106,12 @@ clutter_actor_add_child_internal (ClutterActor *self,
if (self->priv->in_cloned_branch)
clutter_actor_push_in_cloned_branch (child, self->priv->in_cloned_branch);
/* 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
@@ -13639,12 +13712,29 @@ clutter_actor_reparent (ClutterActor *self,
if (old_parent != NULL)
{
/* this will have to call unparent() */
clutter_container_remove_actor (CLUTTER_CONTAINER (old_parent), self);
/* 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() */
clutter_container_add_actor (CLUTTER_CONTAINER (new_parent), self);
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);
priv->needs_compute_resource_scale = TRUE;
@@ -15319,7 +15409,7 @@ clutter_actor_transform_stage_point (ClutterActor *self,
gfloat *x_out,
gfloat *y_out)
{
graphene_point3d_t v[4];
ClutterVertex v[4];
double ST[3][3];
double RQ[3][3];
int du, dv;
@@ -16736,6 +16826,100 @@ clutter_actor_get_text_direction (ClutterActor *self)
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:
*
* |[<!-- language="C" -->
* 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
@@ -17795,9 +17979,9 @@ clutter_actor_get_paint_box (ClutterActor *self,
}
static gboolean
_clutter_actor_get_resource_scale_for_rect (ClutterActor *self,
graphene_rect_t *bounding_rect,
float *resource_scale)
_clutter_actor_get_resource_scale_for_rect (ClutterActor *self,
ClutterRect *bounding_rect,
float *resource_scale)
{
ClutterActor *stage;
float max_scale = 0;
@@ -17820,7 +18004,7 @@ static gboolean
_clutter_actor_compute_resource_scale (ClutterActor *self,
float *resource_scale)
{
graphene_rect_t bounding_rect;
ClutterRect bounding_rect;
ClutterActorPrivate *priv = self->priv;
if (CLUTTER_ACTOR_IN_DESTRUCTION (self) ||
@@ -18364,13 +18548,13 @@ clutter_actor_get_layout_manager (ClutterActor *self)
}
static const ClutterLayoutInfo default_layout_info = {
GRAPHENE_POINT_INIT_ZERO, /* fixed-pos */
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 */
GRAPHENE_SIZE_INIT_ZERO, /* minimum */
GRAPHENE_SIZE_INIT_ZERO, /* natural */
CLUTTER_SIZE_INIT_ZERO, /* minimum */
CLUTTER_SIZE_INIT_ZERO, /* natural */
};
static void

View File

@@ -233,7 +233,8 @@ struct _ClutterActorClass
ClutterActor *old_parent);
void (* destroy) (ClutterActor *self);
void (* pick) (ClutterActor *actor);
void (* pick) (ClutterActor *actor,
const ClutterColor *color);
gboolean (* queue_redraw) (ClutterActor *actor,
ClutterActor *leaf_that_queued,
@@ -430,7 +431,7 @@ void clutter_actor_get_allocation_box
CLUTTER_EXPORT
void clutter_actor_get_allocation_vertices (ClutterActor *self,
ClutterActor *ancestor,
graphene_point3d_t *verts);
ClutterVertex verts[]);
CLUTTER_EXPORT
gboolean clutter_actor_has_allocation (ClutterActor *self);
CLUTTER_EXPORT
@@ -816,16 +817,16 @@ gboolean clutter_actor_transform_stage_point
gfloat *y_out);
CLUTTER_EXPORT
void clutter_actor_get_abs_allocation_vertices (ClutterActor *self,
graphene_point3d_t *verts);
ClutterVertex verts[]);
CLUTTER_EXPORT
void clutter_actor_apply_transform_to_point (ClutterActor *self,
const graphene_point3d_t *point,
graphene_point3d_t *vertex);
const ClutterVertex *point,
ClutterVertex *vertex);
CLUTTER_EXPORT
void clutter_actor_apply_relative_transform_to_point (ClutterActor *self,
ClutterActor *ancestor,
const graphene_point3d_t *point,
graphene_point3d_t *vertex);
const ClutterVertex *point,
ClutterVertex *vertex);
/* Implicit animations */
CLUTTER_EXPORT

View File

@@ -93,6 +93,10 @@ 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__ */

View File

@@ -627,7 +627,7 @@ clutter_backend_init (ClutterBackend *self)
self->units_per_em = -1.0;
self->units_serial = 1;
self->dummy_onscreen = NULL;
self->dummy_onscreen = COGL_INVALID_HANDLE;
}
void
@@ -1012,7 +1012,7 @@ _clutter_backend_get_keymap_direction (ClutterBackend *backend)
void
_clutter_backend_reset_cogl_framebuffer (ClutterBackend *backend)
{
if (backend->dummy_onscreen == NULL)
if (backend->dummy_onscreen == COGL_INVALID_HANDLE)
{
GError *internal_error = NULL;

File diff suppressed because it is too large Load Diff

View File

@@ -152,9 +152,7 @@ clutter_bind_constraint_update_allocation (ClutterConstraint *constraint,
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (constraint);
gfloat source_width, source_height;
gfloat actor_width, actor_height;
graphene_point3d_t source_position;
source_position = GRAPHENE_POINT3D_INIT (0.f, 0.f, 0.f);
ClutterVertex source_position = { 0., };
if (bind->source == NULL)
return;

View File

@@ -182,7 +182,7 @@ clutter_blur_effect_modify_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
{
gfloat cur_width, cur_height;
graphene_point3d_t origin;
ClutterVertex origin;
clutter_paint_volume_get_origin (volume, &origin);
cur_width = clutter_paint_volume_get_width (volume);

View File

@@ -118,6 +118,37 @@ container_real_remove (ClutterContainer *container,
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,
@@ -212,6 +243,7 @@ clutter_container_default_init (ClutterContainerInterface *iface)
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;
@@ -501,6 +533,15 @@ clutter_container_remove_valist (ClutterContainer *container,
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
@@ -518,9 +559,108 @@ clutter_container_remove_valist (ClutterContainer *container,
GList *
clutter_container_get_children (ClutterContainer *container)
{
GList *retval;
g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL);
return clutter_actor_get_children (CLUTTER_ACTOR (container));
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);
}
/**

View File

@@ -59,6 +59,14 @@ typedef struct _ClutterContainerIface ClutterContainerIface;
* 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
@@ -80,7 +88,7 @@ typedef struct _ClutterContainerIface ClutterContainerIface;
* @actor_removed: class handler for #ClutterContainer::actor-removed
* @child_notify: class handler for #ClutterContainer::child-notify
*
* Base interface for container actors. The @add and @remove
* Base interface for container actors. The @add, @remove and @foreach
* virtual functions must be provided by any implementation; the other
* virtual functions are optional.
*
@@ -96,6 +104,13 @@ struct _ClutterContainerIface
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,

View File

@@ -177,7 +177,7 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
if (priv->is_dirty)
{
graphene_rect_t rect;
ClutterRect rect;
gboolean mapped_buffer;
CoglVertexP3T2C4 *verts;
ClutterActor *actor;
@@ -193,8 +193,8 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
*/
if (clutter_offscreen_effect_get_target_rect (effect, &rect))
{
width = graphene_rect_get_width (&rect);
height = graphene_rect_get_height (&rect);
width = clutter_rect_get_width (&rect);
height = clutter_rect_get_height (&rect);
}
else
clutter_actor_get_size (actor, &width, &height);

View File

@@ -81,7 +81,7 @@ struct _ClutterDragActionPrivate
gint y_drag_threshold;
ClutterActor *drag_handle;
ClutterDragAxis drag_axis;
graphene_rect_t drag_area;
ClutterRect drag_area;
ClutterInputDevice *device;
ClutterEventSequence *sequence;
@@ -542,7 +542,7 @@ clutter_drag_action_real_drag_motion (ClutterDragAction *action,
if (action->priv->drag_area_set)
{
graphene_rect_t *drag_area = &action->priv->drag_area;
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);
@@ -811,7 +811,7 @@ clutter_drag_action_class_init (ClutterDragActionClass *klass)
g_param_spec_boxed ("drag-area",
P_("Drag Area"),
P_("Constrains the dragging to a rectangle"),
GRAPHENE_TYPE_RECT,
CLUTTER_TYPE_RECT,
CLUTTER_PARAM_READWRITE);
/**
@@ -1267,10 +1267,10 @@ clutter_drag_action_get_motion_coords (ClutterDragAction *action,
/**
* clutter_drag_action_get_drag_area:
* @action: a #ClutterDragAction
* @drag_area: (out caller-allocates): a #graphene_rect_t to be filled
* @drag_area: (out caller-allocates): a #ClutterRect to be filled
*
* Retrieves the "drag area" associated with @action, that
* is a #graphene_rect_t that constrains the actor movements,
* is a #ClutterRect that constrains the actor movements,
* in parents coordinates.
*
* Returns: %TRUE if the actor is actually constrained (and thus
@@ -1278,7 +1278,7 @@ clutter_drag_action_get_motion_coords (ClutterDragAction *action,
*/
gboolean
clutter_drag_action_get_drag_area (ClutterDragAction *action,
graphene_rect_t *drag_area)
ClutterRect *drag_area)
{
g_return_val_if_fail (CLUTTER_IS_DRAG_ACTION (action), FALSE);
@@ -1298,8 +1298,8 @@ clutter_drag_action_get_drag_area (ClutterDragAction *action,
* If @drag_area is %NULL, the actor is not constrained.
*/
void
clutter_drag_action_set_drag_area (ClutterDragAction *action,
const graphene_rect_t *drag_area)
clutter_drag_action_set_drag_area (ClutterDragAction *action,
const ClutterRect *drag_area)
{
ClutterDragActionPrivate *priv;

View File

@@ -141,11 +141,11 @@ void clutter_drag_action_get_motion_coords (ClutterDragAction *actio
CLUTTER_EXPORT
gboolean clutter_drag_action_get_drag_area (ClutterDragAction *action,
graphene_rect_t *drag_area);
ClutterRect *drag_area);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_area (ClutterDragAction *action,
const graphene_rect_t *drag_area);
void clutter_drag_action_set_drag_area (ClutterDragAction *action,
const ClutterRect *drag_area);
G_END_DECLS

View File

@@ -100,13 +100,13 @@
* // Clear the previous state //
* if (self->rect_1)
* {
* cogl_object_unref (self->rect_1);
* cogl_handle_unref (self->rect_1);
* self->rect_1 = NULL;
* }
*
* if (self->rect_2)
* {
* cogl_object_unref (self->rect_2);
* cogl_handle_unref (self->rect_2);
* self->rect_2 = NULL;
* }
*

View File

@@ -370,7 +370,7 @@ clutter_event_get_coords (const ClutterEvent *event,
gfloat *x,
gfloat *y)
{
graphene_point_t coords;
ClutterPoint coords;
g_return_if_fail (event != NULL);
@@ -386,15 +386,15 @@ clutter_event_get_coords (const ClutterEvent *event,
/**
* clutter_event_get_position:
* @event: a #ClutterEvent
* @position: a #graphene_point_t
* @position: a #ClutterPoint
*
* Retrieves the event coordinates as a #graphene_point_t.
* Retrieves the event coordinates as a #ClutterPoint.
*
* Since: 1.12
*/
void
clutter_event_get_position (const ClutterEvent *event,
graphene_point_t *position)
ClutterPoint *position)
{
g_return_if_fail (event != NULL);
g_return_if_fail (position != NULL);
@@ -415,42 +415,42 @@ clutter_event_get_position (const ClutterEvent *event,
case CLUTTER_PAD_BUTTON_RELEASE:
case CLUTTER_PAD_STRIP:
case CLUTTER_PAD_RING:
graphene_point_init (position, 0.f, 0.f);
clutter_point_init (position, 0.f, 0.f);
break;
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
graphene_point_init (position, event->crossing.x, event->crossing.y);
clutter_point_init (position, event->crossing.x, event->crossing.y);
break;
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
graphene_point_init (position, event->button.x, event->button.y);
clutter_point_init (position, event->button.x, event->button.y);
break;
case CLUTTER_MOTION:
graphene_point_init (position, event->motion.x, event->motion.y);
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:
graphene_point_init (position, event->touch.x, event->touch.y);
clutter_point_init (position, event->touch.x, event->touch.y);
break;
case CLUTTER_SCROLL:
graphene_point_init (position, event->scroll.x, event->scroll.y);
clutter_point_init (position, event->scroll.x, event->scroll.y);
break;
case CLUTTER_TOUCHPAD_PINCH:
graphene_point_init (position, event->touchpad_pinch.x,
event->touchpad_pinch.y);
clutter_point_init (position, event->touchpad_pinch.x,
event->touchpad_pinch.y);
break;
case CLUTTER_TOUCHPAD_SWIPE:
graphene_point_init (position, event->touchpad_swipe.x,
event->touchpad_swipe.y);
clutter_point_init (position, event->touchpad_swipe.x,
event->touchpad_swipe.y);
break;
}
@@ -1796,12 +1796,12 @@ float
clutter_event_get_distance (const ClutterEvent *source,
const ClutterEvent *target)
{
graphene_point_t p0, p1;
ClutterPoint p0, p1;
clutter_event_get_position (source, &p0);
clutter_event_get_position (source, &p1);
return graphene_point_distance (&p0, &p1, NULL, NULL);
return clutter_point_distance (&p0, &p1, NULL, NULL);
}
/**
@@ -1822,17 +1822,17 @@ double
clutter_event_get_angle (const ClutterEvent *source,
const ClutterEvent *target)
{
graphene_point_t p0, p1;
ClutterPoint p0, p1;
float x_distance, y_distance;
double angle;
clutter_event_get_position (source, &p0);
clutter_event_get_position (target, &p1);
if (graphene_point_equal (&p0, &p1))
if (clutter_point_equals (&p0, &p1))
return 0;
graphene_point_distance (&p0, &p1, &x_distance, &y_distance);
clutter_point_distance (&p0, &p1, &x_distance, &y_distance);
angle = atan2 (x_distance, y_distance);

View File

@@ -686,7 +686,7 @@ void clutter_event_get_coords (const ClutterEv
gfloat *y);
CLUTTER_EXPORT
void clutter_event_get_position (const ClutterEvent *event,
graphene_point_t *position);
ClutterPoint *position);
CLUTTER_EXPORT
float clutter_event_get_distance (const ClutterEvent *source,
const ClutterEvent *target);

View File

@@ -1,111 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* Copyright (C) 2019 Endless, Inc
* 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 <http://www.gnu.org/licenses/>.
*/
#include "clutter-build-config.h"
#include "clutter-graphene.h"
#include "clutter-private.h"
#include "clutter-types.h"
static gboolean
graphene_point_progress (const GValue *a,
const GValue *b,
double progress,
GValue *retval)
{
const graphene_point_t *ap = g_value_get_boxed (a);
const graphene_point_t *bp = g_value_get_boxed (b);
graphene_point_t res;
graphene_point_interpolate (ap, bp, progress, &res);
g_value_set_boxed (retval, &res);
return TRUE;
}
static gboolean
graphene_point3d_progress (const GValue *a,
const GValue *b,
double progress,
GValue *retval)
{
const graphene_point3d_t *av = g_value_get_boxed (a);
const graphene_point3d_t *bv = g_value_get_boxed (b);
graphene_point3d_t res;
graphene_point3d_interpolate (av, bv, progress, &res);
g_value_set_boxed (retval, &res);
return TRUE;
}
static gboolean
graphene_rect_progress (const GValue *a,
const GValue *b,
double progress,
GValue *retval)
{
const graphene_rect_t *rect_a = g_value_get_boxed (a);
const graphene_rect_t *rect_b = g_value_get_boxed (b);
graphene_rect_t res;
graphene_rect_interpolate (rect_a, rect_b, progress, &res);
g_value_set_boxed (retval, &res);
return TRUE;
}
static gboolean
graphene_size_progress (const GValue *a,
const GValue *b,
double progress,
GValue *retval)
{
const graphene_size_t *as = g_value_get_boxed (a);
const graphene_size_t *bs = g_value_get_boxed (b);
graphene_size_t res;
graphene_size_interpolate (as, bs, progress, &res);
g_value_set_boxed (retval, &res);
return TRUE;
}
void
clutter_graphene_init (void)
{
clutter_interval_register_progress_func (GRAPHENE_TYPE_POINT,
graphene_point_progress);
clutter_interval_register_progress_func (GRAPHENE_TYPE_POINT3D,
graphene_point3d_progress);
clutter_interval_register_progress_func (GRAPHENE_TYPE_RECT,
graphene_rect_progress);
clutter_interval_register_progress_func (GRAPHENE_TYPE_SIZE,
graphene_size_progress);
}

View File

@@ -1,30 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* Copyright (C) 2019 Endless, Inc
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_GRAPHENE_H
#define CLUTTER_GRAPHENE_H
void clutter_graphene_init (void);
#endif

View File

@@ -991,7 +991,7 @@ clutter_input_device_get_enabled (ClutterInputDevice *device)
gboolean
clutter_input_device_get_coords (ClutterInputDevice *device,
ClutterEventSequence *sequence,
graphene_point_t *point)
ClutterPoint *point)
{
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
g_return_val_if_fail (point != NULL, FALSE);
@@ -1038,7 +1038,7 @@ _clutter_input_device_update (ClutterInputDevice *device,
ClutterStage *stage;
ClutterActor *new_cursor_actor;
ClutterActor *old_cursor_actor;
graphene_point_t point = GRAPHENE_POINT_INIT (-1.0f, -1.0f);
ClutterPoint point = { -1, -1 };
ClutterInputDeviceType device_type = device->device_type;
g_assert (device_type != CLUTTER_KEYBOARD_DEVICE &&

View File

@@ -58,7 +58,7 @@ gint clutter_input_device_get_device_id (ClutterInputDev
CLUTTER_EXPORT
gboolean clutter_input_device_get_coords (ClutterInputDevice *device,
ClutterEventSequence *sequence,
graphene_point_t *point);
ClutterPoint *point);
CLUTTER_EXPORT
ClutterModifierType clutter_input_device_get_modifier_state (ClutterInputDevice *device);
CLUTTER_EXPORT

View File

@@ -89,8 +89,8 @@ clutter_input_focus_reset (ClutterInputFocus *focus)
}
void
clutter_input_focus_set_cursor_location (ClutterInputFocus *focus,
const graphene_rect_t *rect)
clutter_input_focus_set_cursor_location (ClutterInputFocus *focus,
const ClutterRect *rect)
{
ClutterInputFocusPrivate *priv;

View File

@@ -57,8 +57,8 @@ gboolean clutter_input_focus_is_focused (ClutterInputFocus *focus);
CLUTTER_EXPORT
void clutter_input_focus_reset (ClutterInputFocus *focus);
CLUTTER_EXPORT
void clutter_input_focus_set_cursor_location (ClutterInputFocus *focus,
const graphene_rect_t *rect);
void clutter_input_focus_set_cursor_location (ClutterInputFocus *focus,
const ClutterRect *rect);
CLUTTER_EXPORT
void clutter_input_focus_set_surrounding (ClutterInputFocus *focus,

View File

@@ -26,8 +26,8 @@ ClutterInputFocus * clutter_input_method_get_focus (ClutterInputMethod *method);
void clutter_input_method_reset (ClutterInputMethod *method);
void clutter_input_method_set_cursor_location (ClutterInputMethod *method,
const graphene_rect_t *rect);
void clutter_input_method_set_cursor_location (ClutterInputMethod *method,
const ClutterRect *rect);
void clutter_input_method_set_surrounding (ClutterInputMethod *method,
const gchar *text,
guint cursor,

View File

@@ -187,7 +187,7 @@ clutter_input_method_class_init (ClutterInputMethodClass *klass)
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 1, GRAPHENE_TYPE_RECT);
G_TYPE_NONE, 1, CLUTTER_TYPE_RECT);
pspecs[PROP_CONTENT_HINTS] =
g_param_spec_flags ("content-hints",
@@ -377,8 +377,8 @@ clutter_input_method_reset (ClutterInputMethod *im)
}
void
clutter_input_method_set_cursor_location (ClutterInputMethod *im,
const graphene_rect_t *rect)
clutter_input_method_set_cursor_location (ClutterInputMethod *im,
const ClutterRect *rect)
{
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));

View File

@@ -42,8 +42,8 @@ struct _ClutterInputMethodClass
void (* reset) (ClutterInputMethod *im);
void (* set_cursor_location) (ClutterInputMethod *im,
const graphene_rect_t *rect);
void (* set_cursor_location) (ClutterInputMethod *im,
const ClutterRect *rect);
void (* set_surrounding) (ClutterInputMethod *im,
const gchar *text,
guint cursor,

View File

@@ -59,7 +59,6 @@
#include "clutter-event-private.h"
#include "clutter-feature.h"
#include "clutter-input-pointer-a11y-private.h"
#include "clutter-graphene.h"
#include "clutter-main.h"
#include "clutter-master-clock.h"
#include "clutter-mutter.h"
@@ -2195,8 +2194,6 @@ clutter_base_init (void)
/* initialise the Big Clutter Lock™ if necessary */
clutter_threads_init_default ();
clutter_graphene_init ();
}
}

View File

@@ -86,7 +86,7 @@ struct _ClutterOffscreenEffectPrivate
ClutterActor *actor;
ClutterActor *stage;
graphene_point3d_t position;
ClutterVertex position;
int fbo_offset_x;
int fbo_offset_y;
@@ -119,7 +119,7 @@ clutter_offscreen_effect_set_actor (ClutterActorMeta *meta,
/* clear out the previous state */
if (priv->offscreen != NULL)
{
cogl_object_unref (priv->offscreen);
cogl_handle_unref (priv->offscreen);
priv->offscreen = NULL;
}
@@ -199,13 +199,13 @@ update_fbo (ClutterEffect *effect,
if (priv->texture != NULL)
{
cogl_object_unref (priv->texture);
cogl_handle_unref (priv->texture);
priv->texture = NULL;
}
if (priv->offscreen != NULL)
{
cogl_object_unref (priv->offscreen);
cogl_handle_unref (priv->offscreen);
priv->offscreen = NULL;
}
@@ -224,7 +224,7 @@ update_fbo (ClutterEffect *effect,
{
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
cogl_object_unref (priv->target);
cogl_handle_unref (priv->target);
priv->target = NULL;
priv->target_width = 0;
@@ -250,11 +250,9 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
gfloat target_width = -1, target_height = -1;
gfloat resource_scale;
gfloat ceiled_resource_scale;
graphene_point3d_t local_offset;
ClutterVertex local_offset = { 0.f, 0.f, 0.f };
gfloat old_viewport[4];
local_offset = GRAPHENE_POINT3D_INIT (0.0f, 0.0f, 0.0f);
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
@@ -489,13 +487,13 @@ clutter_offscreen_effect_finalize (GObject *gobject)
ClutterOffscreenEffectPrivate *priv = self->priv;
if (priv->offscreen)
cogl_object_unref (priv->offscreen);
cogl_handle_unref (priv->offscreen);
if (priv->target)
cogl_object_unref (priv->target);
cogl_handle_unref (priv->target);
if (priv->texture)
cogl_object_unref (priv->texture);
cogl_handle_unref (priv->texture);
G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->finalize (gobject);
}
@@ -539,7 +537,7 @@ clutter_offscreen_effect_init (ClutterOffscreenEffect *self)
* 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 %NULL. The
* 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
*
@@ -604,7 +602,7 @@ clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect)
* Calls the create_texture() virtual function of the @effect
*
* Return value: (transfer full): a handle to a Cogl texture, or
* %NULL. The returned handle has its reference
* %COGL_INVALID_HANDLE. The returned handle has its reference
* count increased.
*
* Since: 1.4
@@ -684,7 +682,7 @@ clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect,
*/
gboolean
clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect,
graphene_rect_t *rect)
ClutterRect *rect)
{
ClutterOffscreenEffectPrivate *priv;
@@ -696,11 +694,11 @@ clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect,
if (priv->texture == NULL)
return FALSE;
graphene_rect_init (rect,
priv->position.x,
priv->position.y,
cogl_texture_get_width (priv->texture),
cogl_texture_get_height (priv->texture));
clutter_rect_init (rect,
priv->position.x,
priv->position.y,
cogl_texture_get_width (priv->texture),
cogl_texture_get_height (priv->texture));
return TRUE;
}

View File

@@ -114,7 +114,7 @@ gboolean clutter_offscreen_effect_get_target_size (ClutterOffscree
CLUTTER_EXPORT
gboolean clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect,
graphene_rect_t *rect);
ClutterRect *rect);
G_END_DECLS

View File

@@ -58,7 +58,7 @@ struct _ClutterPaintVolume
* elements 4, 5, 6 and 7 most of the time for 2D actors when
* calculating the projected paint box.
*/
graphene_point3d_t vertices[8];
ClutterVertex vertices[8];
/* As an optimization for internally managed PaintVolumes we allow
* initializing ClutterPaintVolume variables allocated on the stack

View File

@@ -63,7 +63,7 @@ _clutter_paint_volume_new (ClutterActor *actor)
pv->actor = actor;
memset (pv->vertices, 0, 8 * sizeof (graphene_point3d_t));
memset (pv->vertices, 0, 8 * sizeof (ClutterVertex));
pv->is_static = FALSE;
pv->is_empty = TRUE;
@@ -96,7 +96,7 @@ _clutter_paint_volume_init_static (ClutterPaintVolume *pv,
{
pv->actor = actor;
memset (pv->vertices, 0, 8 * sizeof (graphene_point3d_t));
memset (pv->vertices, 0, 8 * sizeof (ClutterVertex));
pv->is_static = TRUE;
pv->is_empty = TRUE;
@@ -170,7 +170,7 @@ clutter_paint_volume_free (ClutterPaintVolume *pv)
/**
* clutter_paint_volume_set_origin:
* @pv: a #ClutterPaintVolume
* @origin: a #graphene_point3d_t
* @origin: a #ClutterVertex
*
* Sets the origin of the paint volume.
*
@@ -182,8 +182,8 @@ clutter_paint_volume_free (ClutterPaintVolume *pv)
* Since: 1.6
*/
void
clutter_paint_volume_set_origin (ClutterPaintVolume *pv,
const graphene_point3d_t *origin)
clutter_paint_volume_set_origin (ClutterPaintVolume *pv,
const ClutterVertex *origin)
{
static const int key_vertices[4] = { 0, 1, 3, 4 };
float dx, dy, dz;
@@ -210,7 +210,7 @@ clutter_paint_volume_set_origin (ClutterPaintVolume *pv,
/**
* clutter_paint_volume_get_origin:
* @pv: a #ClutterPaintVolume
* @vertex: (out): the return location for a #graphene_point3d_t
* @vertex: (out): the return location for a #ClutterVertex
*
* Retrieves the origin of the #ClutterPaintVolume.
*
@@ -218,7 +218,7 @@ clutter_paint_volume_set_origin (ClutterPaintVolume *pv,
*/
void
clutter_paint_volume_get_origin (const ClutterPaintVolume *pv,
graphene_point3d_t *vertex)
ClutterVertex *vertex)
{
g_return_if_fail (pv != NULL);
g_return_if_fail (vertex != NULL);
@@ -659,7 +659,7 @@ clutter_paint_volume_union_box (ClutterPaintVolume *pv,
const ClutterActorBox *box)
{
ClutterPaintVolume volume;
graphene_point3d_t origin;
ClutterVertex origin;
g_return_if_fail (pv != NULL);
g_return_if_fail (box != NULL);
@@ -757,7 +757,7 @@ _clutter_paint_volume_get_bounding_box (ClutterPaintVolume *pv,
ClutterActorBox *box)
{
gfloat x_min, y_min, x_max, y_max;
graphene_point3d_t *vertices;
ClutterVertex *vertices;
int count;
gint i;
@@ -878,9 +878,9 @@ _clutter_paint_volume_transform (ClutterPaintVolume *pv,
cogl_matrix_transform_points (matrix,
3,
sizeof (graphene_point3d_t),
sizeof (ClutterVertex),
pv->vertices,
sizeof (graphene_point3d_t),
sizeof (ClutterVertex),
pv->vertices,
transform_count);
@@ -896,7 +896,7 @@ _clutter_paint_volume_axis_align (ClutterPaintVolume *pv)
{
int count;
int i;
graphene_point3d_t origin;
ClutterVertex origin;
float max_x;
float max_y;
float max_z;
@@ -1075,7 +1075,7 @@ _clutter_paint_volume_cull (ClutterPaintVolume *pv,
const ClutterPlane *planes)
{
int vertex_count;
graphene_point3d_t *vertices = pv->vertices;
ClutterVertex *vertices = pv->vertices;
gboolean partial = FALSE;
int i;
int j;
@@ -1097,18 +1097,24 @@ _clutter_paint_volume_cull (ClutterPaintVolume *pv,
for (i = 0; i < 4; i++)
{
const ClutterPlane *plane = &planes[i];
int out = 0;
for (j = 0; j < vertex_count; j++)
{
graphene_vec3_t v;
ClutterVertex p;
float distance;
graphene_vec3_init (&v,
vertices[j].x - graphene_vec3_get_x (&plane->v0),
vertices[j].y - graphene_vec3_get_y (&plane->v0),
vertices[j].z - graphene_vec3_get_z (&plane->v0));
/* 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];
if (graphene_vec3_dot (&plane->n, &v) < 0)
distance = (planes[i].n[0] * p.x +
planes[i].n[1] * p.y +
planes[i].n[2] * p.z);
if (distance < 0)
out++;
}

View File

@@ -64,6 +64,7 @@ typedef struct _ClutterVertex4 ClutterVertex4;
#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)
@@ -107,6 +108,9 @@ typedef enum
/* Used to avoid recursion */
CLUTTER_IN_RELAYOUT = 1 << 6,
/* a flag for internal children of Containers (DEPRECATED) */
CLUTTER_INTERNAL_CHILD = 1 << 7
} ClutterPrivateFlags;
/*
@@ -220,17 +224,17 @@ 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 graphene_point3d_t *vertices_in,
graphene_point3d_t *vertices_out,
int n_vertices);
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_rect_from_rectangle (const cairo_rectangle_int_t *src,
graphene_rect_t *dest);
ClutterRect *dest);
void _clutter_util_rectangle_int_extents (const graphene_rect_t *src,
void _clutter_util_rectangle_int_extents (const ClutterRect *src,
cairo_rectangle_int_t *dest);
void _clutter_util_rectangle_offset (const cairo_rectangle_int_t *src,
@@ -278,10 +282,10 @@ void _clutter_util_matrix_skew_yz (ClutterMatrix *matrix,
float factor);
gboolean _clutter_util_matrix_decompose (const ClutterMatrix *src,
graphene_point3d_t *scale_p,
ClutterVertex *scale_p,
float shear_p[3],
graphene_point3d_t *rotate_p,
graphene_point3d_t *translate_p,
ClutterVertex *rotate_p,
ClutterVertex *translate_p,
ClutterVertex4 *perspective_p);
CLUTTER_EXPORT
@@ -292,8 +296,8 @@ PangoDirection _clutter_pango_find_base_dir (const gchar *text,
typedef struct _ClutterPlane
{
graphene_vec3_t v0;
graphene_vec3_t n;
float v0[3];
float n[3];
} ClutterPlane;
typedef enum _ClutterCullResult

View File

@@ -352,64 +352,63 @@ _clutter_script_parse_knot (ClutterScript *script,
}
static gboolean
parse_rect_from_array (JsonArray *array,
graphene_rect_t *rect)
parse_geometry_from_array (JsonArray *array,
ClutterGeometry *geometry)
{
if (json_array_get_length (array) != 4)
return FALSE;
graphene_rect_init (rect,
json_array_get_int_element (array, 0),
json_array_get_int_element (array, 1),
json_array_get_int_element (array, 2),
json_array_get_int_element (array, 3));
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_rect_from_object (JsonObject *object,
graphene_rect_t *rect)
parse_geometry_from_object (JsonObject *object,
ClutterGeometry *geometry)
{
if (json_object_has_member (object, "x"))
rect->origin.x = json_object_get_int_member (object, "x");
geometry->x = json_object_get_int_member (object, "x");
else
rect->origin.x = 0;
geometry->x = 0;
if (json_object_has_member (object, "y"))
rect->origin.y = json_object_get_int_member (object, "y");
geometry->y = json_object_get_int_member (object, "y");
else
rect->origin.y = 0;
geometry->y = 0;
if (json_object_has_member (object, "width"))
rect->size.width = json_object_get_int_member (object, "width");
geometry->width = json_object_get_int_member (object, "width");
else
rect->size.width = 0;
geometry->width = 0;
if (json_object_has_member (object, "height"))
rect->size.height = json_object_get_int_member (object, "height");
geometry->height = json_object_get_int_member (object, "height");
else
rect->size.height = 0;
geometry->height = 0;
return TRUE;
}
gboolean
_clutter_script_parse_rect (ClutterScript *script,
JsonNode *node,
graphene_rect_t *rect)
_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 (rect != NULL, FALSE);
g_return_val_if_fail (geometry != NULL, FALSE);
switch (JSON_NODE_TYPE (node))
{
case JSON_NODE_ARRAY:
return parse_rect_from_array (json_node_get_array (node), rect);
return parse_geometry_from_array (json_node_get_array (node), geometry);
case JSON_NODE_OBJECT:
return parse_rect_from_object (json_node_get_object (node), rect);
return parse_geometry_from_object (json_node_get_object (node), geometry);
default:
break;
@@ -493,8 +492,8 @@ _clutter_script_parse_color (ClutterScript *script,
}
static gboolean
parse_point_from_array (JsonArray *array,
graphene_point_t *point)
parse_point_from_array (JsonArray *array,
ClutterPoint *point)
{
if (json_array_get_length (array) != 2)
return FALSE;
@@ -506,8 +505,8 @@ parse_point_from_array (JsonArray *array,
}
static gboolean
parse_point_from_object (JsonObject *object,
graphene_point_t *point)
parse_point_from_object (JsonObject *object,
ClutterPoint *point)
{
if (json_object_has_member (object, "x"))
point->x = json_object_get_double_member (object, "x");
@@ -523,9 +522,9 @@ parse_point_from_object (JsonObject *object,
}
gboolean
_clutter_script_parse_point (ClutterScript *script,
JsonNode *node,
graphene_point_t *point)
_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);
@@ -547,8 +546,8 @@ _clutter_script_parse_point (ClutterScript *script,
}
static gboolean
parse_size_from_array (JsonArray *array,
graphene_size_t *size)
parse_size_from_array (JsonArray *array,
ClutterSize *size)
{
if (json_array_get_length (array) != 2)
return FALSE;
@@ -560,8 +559,8 @@ parse_size_from_array (JsonArray *array,
}
static gboolean
parse_size_from_object (JsonObject *object,
graphene_size_t *size)
parse_size_from_object (JsonObject *object,
ClutterSize *size)
{
if (json_object_has_member (object, "width"))
size->width = json_object_get_double_member (object, "width");
@@ -577,9 +576,9 @@ parse_size_from_object (JsonObject *object,
}
gboolean
_clutter_script_parse_size (ClutterScript *script,
JsonNode *node,
graphene_size_t *size)
_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);
@@ -1329,11 +1328,11 @@ _clutter_script_parse_node (ClutterScript *script,
return TRUE;
}
}
else if (p_type == GRAPHENE_TYPE_RECT)
else if (p_type == CLUTTER_TYPE_GEOMETRY)
{
graphene_rect_t rect = GRAPHENE_RECT_INIT_ZERO;
ClutterGeometry geom = { 0, };
/* rect := {
/* geometry := {
* "x" : (int),
* "y" : (int),
* "width" : (int),
@@ -1341,9 +1340,9 @@ _clutter_script_parse_node (ClutterScript *script,
* }
*/
if (_clutter_script_parse_rect (script, node, &rect))
if (_clutter_script_parse_geometry (script, node, &geom))
{
g_value_set_boxed (value, &rect);
g_value_set_boxed (value, &geom);
return TRUE;
}
}
@@ -1365,9 +1364,9 @@ _clutter_script_parse_node (ClutterScript *script,
return TRUE;
}
}
else if (p_type == GRAPHENE_TYPE_POINT)
else if (p_type == CLUTTER_TYPE_POINT)
{
graphene_point_t point = GRAPHENE_POINT_INIT_ZERO;
ClutterPoint point = CLUTTER_POINT_INIT_ZERO;
if (_clutter_script_parse_point (script, node, &point))
{
@@ -1375,9 +1374,9 @@ _clutter_script_parse_node (ClutterScript *script,
return TRUE;
}
}
else if (p_type == GRAPHENE_TYPE_SIZE)
else if (p_type == CLUTTER_TYPE_SIZE)
{
graphene_size_t size = GRAPHENE_SIZE_INIT_ZERO;
ClutterSize size = CLUTTER_SIZE_INIT_ZERO;
if (_clutter_script_parse_size (script, node, &size))
{
@@ -1418,15 +1417,15 @@ _clutter_script_parse_node (ClutterScript *script,
return TRUE;
}
}
else if (G_VALUE_HOLDS (value, GRAPHENE_TYPE_RECT))
else if (G_VALUE_HOLDS (value, CLUTTER_TYPE_GEOMETRY))
{
graphene_rect_t rect = GRAPHENE_RECT_INIT_ZERO;
ClutterGeometry geom = { 0, };
/* rect := [ (int), (int), (int), (int) ] */
/* geometry := [ (int), (int), (int), (int) ] */
if (_clutter_script_parse_rect (script, node, &rect))
if (_clutter_script_parse_geometry (script, node, &geom))
{
g_value_set_boxed (value, &rect);
g_value_set_boxed (value, &geom);
return TRUE;
}
}
@@ -1442,9 +1441,9 @@ _clutter_script_parse_node (ClutterScript *script,
return TRUE;
}
}
else if (G_VALUE_HOLDS (value, GRAPHENE_TYPE_POINT))
else if (G_VALUE_HOLDS (value, CLUTTER_TYPE_POINT))
{
graphene_point_t point = GRAPHENE_POINT_INIT_ZERO;
ClutterPoint point = CLUTTER_POINT_INIT_ZERO;
if (_clutter_script_parse_point (script, node, &point))
{
@@ -1452,9 +1451,9 @@ _clutter_script_parse_node (ClutterScript *script,
return TRUE;
}
}
else if (G_VALUE_HOLDS (value, GRAPHENE_TYPE_SIZE))
else if (G_VALUE_HOLDS (value, CLUTTER_TYPE_SIZE))
{
graphene_size_t size = GRAPHENE_SIZE_INIT_ZERO;
ClutterSize size = CLUTTER_SIZE_INIT_ZERO;
if (_clutter_script_parse_size (script, node, &size))
{

View File

@@ -122,20 +122,20 @@ gboolean _clutter_script_flags_from_string (GType gtype,
gboolean _clutter_script_parse_knot (ClutterScript *script,
JsonNode *node,
ClutterKnot *knot);
gboolean _clutter_script_parse_rect (ClutterScript *script,
gboolean _clutter_script_parse_geometry (ClutterScript *script,
JsonNode *node,
graphene_rect_t *rect);
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,
graphene_point_t *point);
gboolean _clutter_script_parse_point (ClutterScript *script,
JsonNode *node,
ClutterPoint *point);
gboolean _clutter_script_parse_size (ClutterScript *script,
JsonNode *node,
graphene_size_t *size);
ClutterSize *size);
gboolean _clutter_script_parse_translatable_string (ClutterScript *script,
JsonNode *node,

View File

@@ -56,7 +56,7 @@
struct _ClutterScrollActorPrivate
{
graphene_point_t scroll_to;
ClutterPoint scroll_to;
ClutterScrollMode scroll_mode;
@@ -94,19 +94,19 @@ G_DEFINE_TYPE_WITH_CODE (ClutterScrollActor, clutter_scroll_actor, CLUTTER_TYPE_
clutter_animatable_iface_init))
static void
clutter_scroll_actor_set_scroll_to_internal (ClutterScrollActor *self,
const graphene_point_t *point)
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 (graphene_point_equal (&priv->scroll_to, point))
if (clutter_point_equals (&priv->scroll_to, point))
return;
if (point == NULL)
graphene_point_init (&priv->scroll_to, 0.f, 0.f);
clutter_point_init (&priv->scroll_to, 0.f, 0.f);
else
priv->scroll_to = *point;
@@ -216,7 +216,7 @@ clutter_scroll_actor_set_final_state (ClutterAnimatable *animatable,
if (strcmp (property_name, "scroll-to") == 0)
{
ClutterScrollActor *self = CLUTTER_SCROLL_ACTOR (animatable);
const graphene_point_t *point = g_value_get_boxed (value);
const ClutterPoint *point = g_value_get_boxed (value);
clutter_scroll_actor_set_scroll_to_internal (self, point);
}
@@ -248,7 +248,7 @@ clutter_animatable_iface_init (ClutterAnimatableInterface *iface)
g_param_spec_boxed ("scroll-to",
"Scroll To",
"The point to scroll the actor to",
GRAPHENE_TYPE_POINT,
CLUTTER_TYPE_POINT,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
CLUTTER_PARAM_ANIMATABLE);
@@ -322,7 +322,7 @@ clutter_scroll_actor_get_scroll_mode (ClutterScrollActor *actor)
/**
* clutter_scroll_actor_scroll_to_point:
* @actor: a #ClutterScrollActor
* @point: a #graphene_point_t
* @point: a #ClutterPoint
*
* Scrolls the contents of @actor so that @point is the new origin
* of the visible area.
@@ -335,8 +335,8 @@ clutter_scroll_actor_get_scroll_mode (ClutterScrollActor *actor)
* Since: 1.12
*/
void
clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor,
const graphene_point_t *point)
clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor,
const ClutterPoint *point)
{
ClutterScrollActorPrivate *priv;
const ClutterAnimationInfo *info;
@@ -390,10 +390,10 @@ clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor,
/* if a transition already exist, update its bounds */
clutter_transition_set_from (priv->transition,
GRAPHENE_TYPE_POINT,
CLUTTER_TYPE_POINT,
&priv->scroll_to);
clutter_transition_set_to (priv->transition,
GRAPHENE_TYPE_POINT,
CLUTTER_TYPE_POINT,
point);
/* always use the current easing state */
@@ -417,10 +417,10 @@ clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor,
* Since: 1.12
*/
void
clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor,
const graphene_rect_t *rect)
clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor,
const ClutterRect *rect)
{
graphene_rect_t n_rect;
ClutterRect n_rect;
g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor));
g_return_if_fail (rect != NULL);
@@ -428,7 +428,7 @@ clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor,
n_rect = *rect;
/* normalize, so that we have a valid origin */
graphene_rect_normalize (&n_rect);
clutter_rect_normalize (&n_rect);
clutter_scroll_actor_scroll_to_point (actor, &n_rect.origin);
}

View File

@@ -86,11 +86,11 @@ CLUTTER_EXPORT
ClutterScrollMode clutter_scroll_actor_get_scroll_mode (ClutterScrollActor *actor);
CLUTTER_EXPORT
void clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor,
const graphene_point_t *point);
void clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor,
const ClutterPoint *point);
CLUTTER_EXPORT
void clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor,
const graphene_rect_t *rect);
void clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor,
const ClutterRect *rect);
G_END_DECLS

View File

@@ -177,18 +177,18 @@ clutter_shader_effect_clear (ClutterShaderEffect *self,
{
ClutterShaderEffectPrivate *priv = self->priv;
if (priv->shader != NULL)
if (priv->shader != COGL_INVALID_HANDLE)
{
cogl_object_unref (priv->shader);
cogl_handle_unref (priv->shader);
priv->shader = NULL;
priv->shader = COGL_INVALID_HANDLE;
}
if (priv->program != NULL)
if (priv->program != COGL_INVALID_HANDLE)
{
cogl_object_unref (priv->program);
cogl_handle_unref (priv->program);
priv->program = NULL;
priv->program = COGL_INVALID_HANDLE;
}
if (reset_uniforms && priv->uniforms != NULL)
@@ -208,7 +208,7 @@ clutter_shader_effect_update_uniforms (ClutterShaderEffect *effect)
gpointer key, value;
gsize size;
if (priv->program == NULL)
if (priv->program == COGL_INVALID_HANDLE)
return;
if (priv->uniforms == NULL)
@@ -333,7 +333,7 @@ clutter_shader_effect_create_shader (ClutterShaderEffect *self)
default:
g_assert_not_reached ();
return NULL;
return COGL_INVALID_HANDLE;
}
}
@@ -353,7 +353,7 @@ clutter_shader_effect_try_static_source (ClutterShaderEffect *self)
CLUTTER_TYPE_SHADER_EFFECT,
ClutterShaderEffectClassPrivate);
if (class_priv->shader == NULL)
if (class_priv->shader == COGL_INVALID_HANDLE)
{
gchar *source;
@@ -387,10 +387,10 @@ clutter_shader_effect_try_static_source (ClutterShaderEffect *self)
}
}
priv->shader = cogl_object_ref (class_priv->shader);
priv->shader = cogl_handle_ref (class_priv->shader);
if (class_priv->program != NULL)
priv->program = cogl_object_ref (class_priv->program);
if (class_priv->program != COGL_INVALID_HANDLE)
priv->program = cogl_handle_ref (class_priv->program);
}
}
@@ -404,13 +404,13 @@ clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect)
/* If the source hasn't been set then we'll try to get it from the
static source instead */
if (priv->shader == NULL)
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 == NULL)
if (priv->program == COGL_INVALID_HANDLE)
goto out;
CLUTTER_NOTE (SHADER, "Applying the shader effect of type '%s'",
@@ -534,7 +534,7 @@ clutter_shader_effect_new (ClutterShaderType shader_type)
* Retrieves a pointer to the shader's handle
*
* Return value: (transfer none): a pointer to the shader's handle,
* or %NULL
* or %COGL_INVALID_HANDLE
*
* Since: 1.4
*/
@@ -542,7 +542,7 @@ CoglHandle
clutter_shader_effect_get_shader (ClutterShaderEffect *effect)
{
g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect),
NULL);
COGL_INVALID_HANDLE);
return effect->priv->shader;
}
@@ -554,7 +554,7 @@ clutter_shader_effect_get_shader (ClutterShaderEffect *effect)
* Retrieves a pointer to the program's handle
*
* Return value: (transfer none): a pointer to the program's handle,
* or %NULL
* or %COGL_INVALID_HANDLE
*
* Since: 1.4
*/
@@ -562,7 +562,7 @@ CoglHandle
clutter_shader_effect_get_program (ClutterShaderEffect *effect)
{
g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect),
NULL);
COGL_INVALID_HANDLE);
return effect->priv->program;
}
@@ -892,7 +892,7 @@ clutter_shader_effect_set_shader_source (ClutterShaderEffect *effect,
priv = effect->priv;
if (priv->shader != NULL)
if (priv->shader != COGL_INVALID_HANDLE)
return TRUE;
priv->shader = clutter_shader_effect_create_shader (effect);

View File

@@ -79,18 +79,18 @@ 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);
void clutter_stage_log_pick (ClutterStage *stage,
const graphene_point_t *vertices,
ClutterActor *actor);
void clutter_stage_log_pick (ClutterStage *stage,
const ClutterPoint *vertices,
ClutterActor *actor);
void clutter_stage_push_pick_clip (ClutterStage *stage,
const graphene_point_t *vertices);
void clutter_stage_push_pick_clip (ClutterStage *stage,
const ClutterPoint *vertices);
void clutter_stage_pop_pick_clip (ClutterStage *stage);
ClutterActor *_clutter_stage_do_pick (ClutterStage *stage,
float x,
float y,
gint x,
gint y,
ClutterPickMode mode);
ClutterPaintVolume *_clutter_stage_paint_volume_stack_allocate (ClutterStage *stage);
@@ -133,9 +133,9 @@ gboolean _clutter_stage_update_state (ClutterStage *stag
void _clutter_stage_set_scale_factor (ClutterStage *stage,
int factor);
gboolean _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
graphene_rect_t *rect,
float *view_scale);
gboolean _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
ClutterRect *rect,
float *view_scale);
void _clutter_stage_presented (ClutterStage *stage,
CoglFrameEvent frame_event,

View File

@@ -30,6 +30,7 @@ enum
PROP_LAYOUT,
PROP_FRAMEBUFFER,
PROP_OFFSCREEN,
PROP_SHADOWFB,
PROP_SCALE,
PROP_LAST
@@ -44,7 +45,10 @@ typedef struct _ClutterStageViewPrivate
CoglFramebuffer *framebuffer;
CoglOffscreen *offscreen;
CoglPipeline *pipeline;
CoglPipeline *offscreen_pipeline;
CoglOffscreen *shadowfb;
CoglPipeline *shadowfb_pipeline;
guint dirty_viewport : 1;
guint dirty_projection : 1;
@@ -78,6 +82,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
if (priv->offscreen)
return priv->offscreen;
else if (priv->shadowfb)
return priv->shadowfb;
else
return priv->framebuffer;
}
@@ -99,6 +105,24 @@ clutter_stage_view_get_onscreen (ClutterStageView *view)
return priv->framebuffer;
}
static CoglPipeline *
clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
{
CoglPipeline *pipeline;
pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer));
cogl_pipeline_set_layer_filters (pipeline, 0,
COGL_PIPELINE_FILTER_NEAREST,
COGL_PIPELINE_FILTER_NEAREST);
cogl_pipeline_set_layer_texture (pipeline, 0,
cogl_offscreen_get_texture (framebuffer));
cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
return pipeline;
}
static void
clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
{
@@ -109,21 +133,27 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
g_assert (priv->offscreen != NULL);
if (priv->pipeline)
if (priv->offscreen_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);
priv->offscreen_pipeline =
clutter_stage_view_create_framebuffer_pipeline (priv->offscreen);
if (view_class->setup_offscreen_blit_pipeline)
view_class->setup_offscreen_blit_pipeline (view, priv->pipeline);
view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
}
static void
clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
if (priv->shadowfb_pipeline)
return;
priv->shadowfb_pipeline =
clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb);
}
void
@@ -132,7 +162,45 @@ 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);
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
}
static void
clutter_stage_view_copy_to_framebuffer (ClutterStageView *view,
const cairo_rectangle_int_t *rect,
CoglPipeline *pipeline,
CoglFramebuffer *src_framebuffer,
CoglFramebuffer *dst_framebuffer,
gboolean can_blit)
{
CoglMatrix matrix;
/* First, try with blit */
if (can_blit)
{
if (cogl_blit_framebuffer (src_framebuffer,
dst_framebuffer,
0, 0,
0, 0,
cogl_framebuffer_get_width (dst_framebuffer),
cogl_framebuffer_get_height (dst_framebuffer),
NULL))
return;
}
/* If blit fails, fallback to the slower painting method */
cogl_framebuffer_push_matrix (dst_framebuffer);
cogl_matrix_init_identity (&matrix);
cogl_matrix_translate (&matrix, -1, 1, 0);
cogl_matrix_scale (&matrix, 2, -2, 0);
cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix);
cogl_framebuffer_draw_rectangle (dst_framebuffer,
pipeline,
0, 0, 1, 1);
cogl_framebuffer_pop_matrix (dst_framebuffer);
}
void
@@ -141,39 +209,46 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view,
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
CoglMatrix matrix;
clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
if (cogl_matrix_is_identity (&matrix))
if (priv->offscreen)
{
int fb_width = cogl_framebuffer_get_width (priv->framebuffer);
int fb_height = cogl_framebuffer_get_height (priv->framebuffer);
gboolean can_blit;
CoglMatrix matrix;
if (cogl_blit_framebuffer (priv->offscreen,
priv->framebuffer,
0, 0,
0, 0,
fb_width, fb_height,
NULL))
return;
clutter_stage_view_ensure_offscreen_blit_pipeline (view);
clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
can_blit = cogl_matrix_is_identity (&matrix);
if (priv->shadowfb)
{
clutter_stage_view_copy_to_framebuffer (view,
rect,
priv->offscreen_pipeline,
priv->offscreen,
priv->shadowfb,
can_blit);
}
else
{
clutter_stage_view_copy_to_framebuffer (view,
rect,
priv->offscreen_pipeline,
priv->offscreen,
priv->framebuffer,
can_blit);
}
}
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);
if (priv->shadowfb)
{
clutter_stage_view_ensure_shadowfb_blit_pipeline (view);
clutter_stage_view_copy_to_framebuffer (view,
rect,
priv->shadowfb_pipeline,
priv->shadowfb,
priv->framebuffer,
TRUE);
}
}
float
@@ -273,6 +348,9 @@ clutter_stage_view_get_property (GObject *object,
case PROP_OFFSCREEN:
g_value_set_boxed (value, priv->offscreen);
break;
case PROP_SHADOWFB:
g_value_set_boxed (value, priv->shadowfb);
break;
case PROP_SCALE:
g_value_set_float (value, priv->scale);
break;
@@ -318,6 +396,9 @@ clutter_stage_view_set_property (GObject *object,
case PROP_OFFSCREEN:
priv->offscreen = g_value_dup_boxed (value);
break;
case PROP_SHADOWFB:
priv->shadowfb = g_value_dup_boxed (value);
break;
case PROP_SCALE:
priv->scale = g_value_get_float (value);
break;
@@ -334,8 +415,10 @@ clutter_stage_view_dispose (GObject *object)
clutter_stage_view_get_instance_private (view);
g_clear_pointer (&priv->framebuffer, cogl_object_unref);
g_clear_pointer (&priv->shadowfb, cogl_object_unref);
g_clear_pointer (&priv->offscreen, cogl_object_unref);
g_clear_pointer (&priv->pipeline, cogl_object_unref);
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
}
@@ -390,6 +473,15 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_SHADOWFB] =
g_param_spec_boxed ("shadowfb",
"Shadow framebuffer",
"Framebuffer used as intermediate shadow buffer",
COGL_TYPE_HANDLE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_SCALE] =
g_param_spec_float ("scale",
"View scale",

View File

@@ -107,7 +107,7 @@ struct _ClutterStageQueueRedrawEntry
typedef struct _PickRecord
{
graphene_point_t vertex[4];
ClutterPoint vertex[4];
ClutterActor *actor;
int clip_stack_top;
} PickRecord;
@@ -115,7 +115,7 @@ typedef struct _PickRecord
typedef struct _PickClipRecord
{
int prev;
graphene_point_t vertex[4];
ClutterPoint vertex[4];
} PickClipRecord;
struct _ClutterStagePrivate
@@ -129,6 +129,8 @@ struct _ClutterStagePrivate
CoglMatrix view;
float viewport[4];
ClutterFog fog;
gchar *title;
ClutterActor *key_focused_actor;
@@ -171,6 +173,7 @@ struct _ClutterStagePrivate
guint relayout_pending : 1;
guint redraw_pending : 1;
guint is_cursor_visible : 1;
guint use_fog : 1;
guint throttle_motion_events : 1;
guint use_alpha : 1;
guint min_size_changed : 1;
@@ -188,6 +191,8 @@ enum
PROP_CURSOR_VISIBLE,
PROP_PERSPECTIVE,
PROP_TITLE,
PROP_USE_FOG,
PROP_FOG,
PROP_USE_ALPHA,
PROP_KEY_FOCUS,
PROP_NO_CLEAR_HINT,
@@ -244,6 +249,20 @@ clutter_stage_real_remove (ClutterContainer *container,
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,
@@ -274,6 +293,7 @@ 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;
@@ -376,9 +396,9 @@ _clutter_stage_clear_pick_stack (ClutterStage *stage)
}
void
clutter_stage_log_pick (ClutterStage *stage,
const graphene_point_t *vertices,
ClutterActor *actor)
clutter_stage_log_pick (ClutterStage *stage,
const ClutterPoint *vertices,
ClutterActor *actor)
{
ClutterStagePrivate *priv;
PickRecord rec;
@@ -390,7 +410,7 @@ clutter_stage_log_pick (ClutterStage *stage,
g_assert (!priv->pick_stack_frozen);
memcpy (rec.vertex, vertices, 4 * sizeof (graphene_point_t));
memcpy (rec.vertex, vertices, 4 * sizeof (ClutterPoint));
rec.actor = actor;
rec.clip_stack_top = priv->pick_clip_stack_top;
@@ -398,8 +418,8 @@ clutter_stage_log_pick (ClutterStage *stage,
}
void
clutter_stage_push_pick_clip (ClutterStage *stage,
const graphene_point_t *vertices)
clutter_stage_push_pick_clip (ClutterStage *stage,
const ClutterPoint *vertices)
{
ClutterStagePrivate *priv;
PickClipRecord clip;
@@ -411,7 +431,7 @@ clutter_stage_push_pick_clip (ClutterStage *stage,
g_assert (!priv->pick_stack_frozen);
clip.prev = priv->pick_clip_stack_top;
memcpy (clip.vertex, vertices, 4 * sizeof (graphene_point_t));
memcpy (clip.vertex, vertices, 4 * sizeof (ClutterPoint));
g_array_append_val (priv->pick_clip_stack, clip);
priv->pick_clip_stack_top = priv->pick_clip_stack->len - 1;
@@ -444,7 +464,7 @@ clutter_stage_pop_pick_clip (ClutterStage *stage)
}
static gboolean
is_quadrilateral_axis_aligned_rectangle (const graphene_point_t *vertices)
is_quadrilateral_axis_aligned_rectangle (const ClutterPoint *vertices)
{
int i;
@@ -462,8 +482,8 @@ is_quadrilateral_axis_aligned_rectangle (const graphene_point_t *vertices)
}
static gboolean
is_inside_axis_aligned_rectangle (const graphene_point_t *point,
const graphene_point_t *vertices)
is_inside_axis_aligned_rectangle (const ClutterPoint *point,
const ClutterPoint *vertices)
{
float min_x = FLT_MAX;
float max_x = FLT_MIN;
@@ -485,79 +505,24 @@ is_inside_axis_aligned_rectangle (const graphene_point_t *point,
point->y < max_y);
}
static int
clutter_point_compare_line (const graphene_point_t *p,
const graphene_point_t *a,
const graphene_point_t *b)
{
graphene_vec3_t vec_pa;
graphene_vec3_t vec_pb;
graphene_vec3_t cross;
float cross_z;
graphene_vec3_init (&vec_pa, p->x - a->x, p->y - a->y, 0.f);
graphene_vec3_init (&vec_pb, p->x - b->x, p->y - b->y, 0.f);
graphene_vec3_cross (&vec_pa, &vec_pb, &cross);
cross_z = graphene_vec3_get_z (&cross);
if (cross_z > 0.f)
return 1;
else if (cross_z < 0.f)
return -1;
else
return 0;
}
static gboolean
is_inside_unaligned_rectangle (const graphene_point_t *point,
const graphene_point_t *vertices)
{
unsigned int i;
int first_side;
first_side = 0;
for (i = 0; i < 4; i++)
{
int side;
side = clutter_point_compare_line (point,
&vertices[i],
&vertices[(i + 1) % 4]);
if (side)
{
if (first_side == 0)
first_side = side;
else if (side != first_side)
return FALSE;
}
}
if (first_side == 0)
return FALSE;
return TRUE;
}
static gboolean
is_inside_input_region (const graphene_point_t *point,
const graphene_point_t *vertices)
is_inside_input_region (const ClutterPoint *point,
const ClutterPoint *vertices)
{
if (is_quadrilateral_axis_aligned_rectangle (vertices))
return is_inside_axis_aligned_rectangle (point, vertices);
else
return is_inside_unaligned_rectangle (point, vertices);
return clutter_point_inside_quadrilateral (point, vertices);
}
static gboolean
pick_record_contains_point (ClutterStage *stage,
pick_record_contains_pixel (ClutterStage *stage,
const PickRecord *rec,
float x,
float y)
int x,
int y)
{
const graphene_point_t point = GRAPHENE_POINT_INIT (x, y);
const ClutterPoint point = CLUTTER_POINT_INIT (x, y);
ClutterStagePrivate *priv;
int clip_index;
@@ -770,9 +735,8 @@ _cogl_util_get_eye_planes_for_screen_poly (float *polygon,
Vector4 *tmp_poly;
ClutterPlane *plane;
int i;
Vector4 *poly;
graphene_vec3_t b;
graphene_vec3_t c;
float b[3];
float c[3];
int count;
tmp_poly = g_alloca (sizeof (Vector4) * n_vertices * 2);
@@ -839,37 +803,23 @@ _cogl_util_get_eye_planes_for_screen_poly (float *polygon,
for (i = 0; i < count; i++)
{
plane = &planes[i];
poly = &tmp_poly[i];
graphene_vec3_init (&plane->v0, poly->x, poly->y, poly->z);
poly = &tmp_poly[n_vertices + i];
graphene_vec3_init (&b, poly->x, poly->y, poly->z);
poly = &tmp_poly[n_vertices + i + 1];
graphene_vec3_init (&c, poly->x, poly->y, poly->z);
graphene_vec3_subtract (&b, &plane->v0, &b);
graphene_vec3_subtract (&c, &plane->v0, &c);
graphene_vec3_cross (&b, &c, &plane->n);
graphene_vec3_normalize (&plane->n, &plane->n);
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];
poly = &tmp_poly[0];
graphene_vec3_init (&plane->v0, poly->x, poly->y, poly->z);
poly = &tmp_poly[2 * n_vertices - 1];
graphene_vec3_init (&b, poly->x, poly->y, poly->z);
poly = &tmp_poly[n_vertices];
graphene_vec3_init (&c, poly->x, poly->y, poly->z);
graphene_vec3_subtract (&b, &plane->v0, &b);
graphene_vec3_subtract (&c, &plane->v0, &c);
graphene_vec3_cross (&b, &c, &plane->n);
graphene_vec3_normalize (&plane->n, &plane->n);
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
@@ -1000,7 +950,8 @@ clutter_stage_paint (ClutterActor *self)
}
static void
clutter_stage_pick (ClutterActor *self)
clutter_stage_pick (ClutterActor *self,
const ClutterColor *color)
{
ClutterActorIter iter;
ClutterActor *child;
@@ -1421,7 +1372,7 @@ _clutter_stage_check_updated_pointers (ClutterStage *stage)
GSList *updating = NULL;
const GSList *devices;
cairo_rectangle_int_t clip;
graphene_point_t point;
ClutterPoint point;
gboolean has_clip;
has_clip = _clutter_stage_window_get_redraw_clip_bounds (priv->impl, &clip);
@@ -1675,8 +1626,8 @@ clutter_stage_get_redraw_clip_bounds (ClutterStage *stage,
static ClutterActor *
_clutter_stage_do_pick_on_view (ClutterStage *stage,
float x,
float y,
gint x,
gint y,
ClutterPickMode mode,
ClutterStageView *view)
{
@@ -1711,7 +1662,7 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
{
const PickRecord *rec = &g_array_index (priv->pick_stack, PickRecord, i);
if (rec->actor && pick_record_contains_point (stage, rec, x, y))
if (rec->actor && pick_record_contains_pixel (stage, rec, x, y))
return rec->actor;
}
@@ -1747,8 +1698,8 @@ clutter_stage_get_view_at (ClutterStage *stage,
ClutterActor *
_clutter_stage_do_pick (ClutterStage *stage,
float x,
float y,
gint x,
gint y,
ClutterPickMode mode)
{
ClutterActor *actor = CLUTTER_ACTOR (stage);
@@ -1865,6 +1816,14 @@ clutter_stage_set_property (GObject *object,
clutter_stage_set_title (stage, g_value_get_string (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;
@@ -1919,6 +1878,14 @@ clutter_stage_get_property (GObject *gobject,
g_value_set_string (value, priv->title);
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;
@@ -2104,6 +2071,41 @@ clutter_stage_class_init (ClutterStageClass *klass)
NULL,
CLUTTER_PARAM_READWRITE);
/**
* 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.
*/
obj_props[PROP_USE_FOG] =
g_param_spec_boolean ("use-fog",
P_("Use Fog"),
P_("Whether to enable depth cueing"),
FALSE,
CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
/**
* 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.
*/
obj_props[PROP_FOG] =
g_param_spec_boxed ("fog",
P_("Fog"),
P_("Settings for the depth cueing"),
CLUTTER_TYPE_FOG,
CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
/**
* ClutterStage:use-alpha:
*
@@ -2341,6 +2343,7 @@ clutter_stage_init (ClutterStage *self)
priv->event_queue = g_queue_new ();
priv->is_cursor_visible = TRUE;
priv->use_fog = FALSE;
priv->throttle_motion_events = TRUE;
priv->min_size_changed = FALSE;
priv->sync_delay = -1;
@@ -2349,6 +2352,10 @@ clutter_stage_init (ClutterStage *self)
clutter_actor_set_background_color (CLUTTER_ACTOR (self),
&default_stage_color);
/* 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);
@@ -2892,8 +2899,8 @@ clutter_stage_read_pixels (ClutterStage *stage,
ClutterActor *
clutter_stage_get_actor_at_pos (ClutterStage *stage,
ClutterPickMode pick_mode,
float x,
float y)
gint x,
gint y)
{
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
@@ -3086,6 +3093,136 @@ clutter_stage_get_key_focus (ClutterStage *stage)
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
@@ -3108,6 +3245,24 @@ 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:
*
@@ -4511,7 +4666,7 @@ clutter_stage_get_capture_final_size (ClutterStage *stage,
if (rect)
{
graphene_rect_t capture_rect;
ClutterRect capture_rect;
_clutter_util_rect_from_rectangle (rect, &capture_rect);
if (!_clutter_stage_get_max_view_scale_factor_for_rect (stage,
@@ -4718,9 +4873,9 @@ clutter_stage_update_resource_scales (ClutterStage *stage)
}
gboolean
_clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
graphene_rect_t *rect,
float *view_scale)
_clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
ClutterRect *rect,
float *view_scale)
{
ClutterStagePrivate *priv = stage->priv;
float scale = 0.0f;
@@ -4730,12 +4885,12 @@ _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
{
ClutterStageView *view = l->data;
cairo_rectangle_int_t view_layout;
graphene_rect_t view_rect;
ClutterRect view_rect;
clutter_stage_view_get_layout (view, &view_layout);
_clutter_util_rect_from_rectangle (&view_layout, &view_rect);
if (graphene_rect_intersection (&view_rect, rect, NULL))
if (clutter_rect_intersection (&view_rect, rect, NULL))
scale = MAX (clutter_stage_view_get_scale (view), scale);
}

View File

@@ -115,6 +115,26 @@ struct _ClutterPerspective
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)
*/
@@ -133,6 +153,8 @@ typedef struct _ClutterCapture
CLUTTER_EXPORT
GType clutter_perspective_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
GType clutter_fog_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
GType clutter_stage_get_type (void) G_GNUC_CONST;
@@ -201,8 +223,8 @@ gboolean clutter_stage_event (ClutterStage
CLUTTER_EXPORT
ClutterActor * clutter_stage_get_actor_at_pos (ClutterStage *stage,
ClutterPickMode pick_mode,
float x,
float y);
gint x,
gint y);
CLUTTER_EXPORT
guchar * clutter_stage_read_pixels (ClutterStage *stage,
gint x,

View File

@@ -157,7 +157,7 @@ struct _ClutterTextPrivate
gint text_logical_y;
/* Where to draw the cursor */
graphene_rect_t cursor_rect;
ClutterRect cursor_rect;
ClutterColor cursor_color;
guint cursor_size;
@@ -1304,7 +1304,7 @@ static inline void
update_cursor_location (ClutterText *self)
{
ClutterTextPrivate *priv = self->priv;
graphene_rect_t rect;
ClutterRect rect;
float x, y;
if (!priv->editable)
@@ -1312,7 +1312,7 @@ update_cursor_location (ClutterText *self)
rect = priv->cursor_rect;
clutter_actor_get_transformed_position (CLUTTER_ACTOR (self), &x, &y);
graphene_rect_offset (&rect, x, y);
clutter_rect_offset (&rect, x, y);
clutter_input_focus_set_cursor_location (priv->input_focus, &rect);
}
@@ -1322,7 +1322,7 @@ clutter_text_ensure_cursor_position (ClutterText *self,
{
ClutterTextPrivate *priv = self->priv;
gfloat x, y, cursor_height;
graphene_rect_t cursor_rect = GRAPHENE_RECT_INIT_ZERO;
ClutterRect cursor_rect = CLUTTER_RECT_INIT_ZERO;
gint position;
position = priv->position;
@@ -1345,17 +1345,25 @@ clutter_text_ensure_cursor_position (ClutterText *self,
&x, &y,
&cursor_height);
graphene_rect_init (&cursor_rect,
x,
y + CURSOR_Y_PADDING * scale,
priv->cursor_size * scale,
cursor_height - 2 * CURSOR_Y_PADDING * scale);
clutter_rect_init (&cursor_rect,
x,
y + CURSOR_Y_PADDING * scale,
priv->cursor_size * scale,
cursor_height - 2 * CURSOR_Y_PADDING * scale);
if (!graphene_rect_equal (&priv->cursor_rect, &cursor_rect))
if (!clutter_rect_equals (&priv->cursor_rect, &cursor_rect))
{
ClutterGeometry cursor_pos;
priv->cursor_rect = cursor_rect;
g_signal_emit (self, text_signals[CURSOR_EVENT], 0, &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);
update_cursor_location (self);
@@ -2704,7 +2712,7 @@ clutter_text_paint (ClutterActor *self)
if (actor_width < text_width)
{
gint cursor_x = graphene_rect_get_x (&priv->cursor_rect);
gint cursor_x = clutter_rect_get_x (&priv->cursor_rect);
if (priv->position == -1)
{
@@ -2791,7 +2799,7 @@ add_selection_to_paint_volume (ClutterText *text,
{
ClutterPaintVolume *total_volume = user_data;
ClutterPaintVolume rect_volume;
graphene_point3d_t vertex;
ClutterVertex vertex;
_clutter_paint_volume_init_static (&rect_volume, CLUTTER_ACTOR (text));
@@ -2813,7 +2821,7 @@ clutter_text_get_paint_volume_for_cursor (ClutterText *text,
ClutterPaintVolume *volume)
{
ClutterTextPrivate *priv = text->priv;
graphene_point3d_t origin;
ClutterVertex origin;
clutter_text_ensure_cursor_position (text, resource_scale);
@@ -2856,7 +2864,7 @@ clutter_text_get_paint_volume (ClutterActor *self,
{
PangoLayout *layout;
PangoRectangle ink_rect;
graphene_point3d_t origin;
ClutterVertex origin;
float resource_scale;
/* If the text is single line editable then it gets clipped to
@@ -4391,10 +4399,10 @@ clutter_text_class_init (ClutterTextClass *klass)
/**
* ClutterText::cursor-event:
* @self: the #ClutterText that emitted the signal
* @rect: the coordinates of the cursor
* @geometry: the coordinates of the cursor
*
* The ::cursor-event signal is emitted whenever the cursor position
* changes inside a #ClutterText actor. Inside @rect it is stored
* changes inside a #ClutterText actor. Inside @geometry it is stored
* the current position and size of the cursor, relative to the actor
* itself.
*
@@ -4409,7 +4417,7 @@ clutter_text_class_init (ClutterTextClass *klass)
G_STRUCT_OFFSET (ClutterTextClass, cursor_event),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
GRAPHENE_TYPE_RECT | G_SIGNAL_TYPE_STATIC_SCOPE);
CLUTTER_TYPE_GEOMETRY | G_SIGNAL_TYPE_STATIC_SCOPE);
/**
* ClutterText::cursor-changed:
@@ -6772,8 +6780,8 @@ clutter_text_get_layout_offsets (ClutterText *self,
* Since: 1.16
*/
void
clutter_text_get_cursor_rect (ClutterText *self,
graphene_rect_t *rect)
clutter_text_get_cursor_rect (ClutterText *self,
ClutterRect *rect)
{
g_return_if_fail (CLUTTER_IS_TEXT (self));
g_return_if_fail (rect != NULL);

View File

@@ -82,7 +82,7 @@ struct _ClutterTextClass
void (* text_changed) (ClutterText *self);
void (* activate) (ClutterText *self);
void (* cursor_event) (ClutterText *self,
const graphene_rect_t *rect);
const ClutterGeometry *geometry);
void (* cursor_changed) (ClutterText *self);
/*< private >*/
@@ -230,7 +230,7 @@ CLUTTER_EXPORT
guint clutter_text_get_cursor_size (ClutterText *self);
CLUTTER_EXPORT
void clutter_text_get_cursor_rect (ClutterText *self,
graphene_rect_t *rect);
ClutterRect *rect);
CLUTTER_EXPORT
void clutter_text_set_selectable (ClutterText *self,
gboolean selectable);

View File

@@ -145,8 +145,8 @@ struct _ClutterTimelinePrivate
ClutterStepMode step_mode;
/* cubic-bezier() parameters */
graphene_point_t cb_1;
graphene_point_t cb_2;
ClutterPoint cb_1;
ClutterPoint cb_2;
guint is_playing : 1;
@@ -846,8 +846,8 @@ clutter_timeline_init (ClutterTimeline *self)
self->priv->step_mode = CLUTTER_STEP_MODE_END;
/* default cubic-bezier() paramereters are (0, 0, 1, 1) */
graphene_point_init (&self->priv->cb_1, 0, 0);
graphene_point_init (&self->priv->cb_2, 1, 1);
clutter_point_init (&self->priv->cb_1, 0, 0);
clutter_point_init (&self->priv->cb_2, 1, 1);
}
struct CheckIfMarkerHitClosure
@@ -2485,9 +2485,9 @@ clutter_timeline_get_step_progress (ClutterTimeline *timeline,
* Since: 1.12
*/
void
clutter_timeline_set_cubic_bezier_progress (ClutterTimeline *timeline,
const graphene_point_t *c_1,
const graphene_point_t *c_2)
clutter_timeline_set_cubic_bezier_progress (ClutterTimeline *timeline,
const ClutterPoint *c_1,
const ClutterPoint *c_2)
{
ClutterTimelinePrivate *priv;
@@ -2522,9 +2522,9 @@ clutter_timeline_set_cubic_bezier_progress (ClutterTimeline *timeline,
* Since: 1.12
*/
gboolean
clutter_timeline_get_cubic_bezier_progress (ClutterTimeline *timeline,
graphene_point_t *c_1,
graphene_point_t *c_2)
clutter_timeline_get_cubic_bezier_progress (ClutterTimeline *timeline,
ClutterPoint *c_1,
ClutterPoint *c_2)
{
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE);

View File

@@ -208,13 +208,13 @@ gboolean clutter_timeline_get_step_progress
gint *n_steps,
ClutterStepMode *step_mode);
CLUTTER_EXPORT
void clutter_timeline_set_cubic_bezier_progress (ClutterTimeline *timeline,
const graphene_point_t *c_1,
const graphene_point_t *c_2);
void clutter_timeline_set_cubic_bezier_progress (ClutterTimeline *timeline,
const ClutterPoint *c_1,
const ClutterPoint *c_2);
CLUTTER_EXPORT
gboolean clutter_timeline_get_cubic_bezier_progress (ClutterTimeline *timeline,
graphene_point_t *c_1,
graphene_point_t *c_2);
gboolean clutter_timeline_get_cubic_bezier_progress (ClutterTimeline *timeline,
ClutterPoint *c_1,
ClutterPoint *c_2);
CLUTTER_EXPORT
gint64 clutter_timeline_get_duration_hint (ClutterTimeline *timeline);

View File

@@ -33,16 +33,20 @@
#include <clutter/clutter-macros.h>
#include <clutter/clutter-enums.h>
#include <graphene-gobject.h>
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;
@@ -75,9 +79,14 @@ 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;
@@ -104,6 +113,7 @@ typedef union _ClutterEvent ClutterEvent;
*/
typedef struct _ClutterEventSequence ClutterEventSequence;
typedef struct _ClutterFog ClutterFog; /* deprecated */
typedef struct _ClutterBehaviour ClutterBehaviour; /* deprecated */
typedef struct _ClutterShader ClutterShader; /* deprecated */
@@ -127,6 +137,310 @@ typedef struct _ClutterShader ClutterShader; /* deprecated */
*/
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_EXPORT
GType clutter_point_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
const ClutterPoint * clutter_point_zero (void);
CLUTTER_EXPORT
ClutterPoint * clutter_point_alloc (void);
CLUTTER_EXPORT
ClutterPoint * clutter_point_init (ClutterPoint *point,
float x,
float y);
CLUTTER_EXPORT
ClutterPoint * clutter_point_copy (const ClutterPoint *point);
CLUTTER_EXPORT
void clutter_point_free (ClutterPoint *point);
CLUTTER_EXPORT
gboolean clutter_point_equals (const ClutterPoint *a,
const ClutterPoint *b);
CLUTTER_EXPORT
float clutter_point_distance (const ClutterPoint *a,
const ClutterPoint *b,
float *x_distance,
float *y_distance);
CLUTTER_EXPORT
gboolean clutter_point_inside_quadrilateral (const ClutterPoint *point,
const ClutterPoint *vertices);
/**
* 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_EXPORT
GType clutter_size_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterSize * clutter_size_alloc (void);
CLUTTER_EXPORT
ClutterSize * clutter_size_init (ClutterSize *size,
float width,
float height);
CLUTTER_EXPORT
ClutterSize * clutter_size_copy (const ClutterSize *size);
CLUTTER_EXPORT
void clutter_size_free (ClutterSize *size);
CLUTTER_EXPORT
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_EXPORT
GType clutter_rect_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
const ClutterRect * clutter_rect_zero (void);
CLUTTER_EXPORT
ClutterRect * clutter_rect_alloc (void);
CLUTTER_EXPORT
ClutterRect * clutter_rect_init (ClutterRect *rect,
float x,
float y,
float width,
float height);
CLUTTER_EXPORT
ClutterRect * clutter_rect_copy (const ClutterRect *rect);
CLUTTER_EXPORT
void clutter_rect_free (ClutterRect *rect);
CLUTTER_EXPORT
gboolean clutter_rect_equals (ClutterRect *a,
ClutterRect *b);
CLUTTER_EXPORT
ClutterRect * clutter_rect_normalize (ClutterRect *rect);
CLUTTER_EXPORT
void clutter_rect_get_center (ClutterRect *rect,
ClutterPoint *center);
CLUTTER_EXPORT
gboolean clutter_rect_contains_point (ClutterRect *rect,
ClutterPoint *point);
CLUTTER_EXPORT
gboolean clutter_rect_contains_rect (ClutterRect *a,
ClutterRect *b);
CLUTTER_EXPORT
void clutter_rect_union (ClutterRect *a,
ClutterRect *b,
ClutterRect *res);
CLUTTER_EXPORT
gboolean clutter_rect_intersection (ClutterRect *a,
ClutterRect *b,
ClutterRect *res);
CLUTTER_EXPORT
void clutter_rect_offset (ClutterRect *rect,
float d_x,
float d_y);
CLUTTER_EXPORT
void clutter_rect_inset (ClutterRect *rect,
float d_x,
float d_y);
CLUTTER_EXPORT
void clutter_rect_scale (ClutterRect *rect,
float s_x,
float s_y);
CLUTTER_EXPORT
void clutter_rect_clamp_to_pixel (ClutterRect *rect);
CLUTTER_EXPORT
float clutter_rect_get_x (ClutterRect *rect);
CLUTTER_EXPORT
float clutter_rect_get_y (ClutterRect *rect);
CLUTTER_EXPORT
float clutter_rect_get_width (ClutterRect *rect);
CLUTTER_EXPORT
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_EXPORT
GType clutter_vertex_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterVertex *clutter_vertex_new (gfloat x,
gfloat y,
gfloat z);
CLUTTER_EXPORT
ClutterVertex *clutter_vertex_alloc (void);
CLUTTER_EXPORT
ClutterVertex *clutter_vertex_init (ClutterVertex *vertex,
gfloat x,
gfloat y,
gfloat z);
CLUTTER_EXPORT
ClutterVertex *clutter_vertex_copy (const ClutterVertex *vertex);
CLUTTER_EXPORT
void clutter_vertex_free (ClutterVertex *vertex);
CLUTTER_EXPORT
gboolean clutter_vertex_equal (const ClutterVertex *vertex_a,
const ClutterVertex *vertex_b);
/**
* ClutterActorBox:
* @x1: X coordinate of the top left corner
@@ -230,8 +544,8 @@ gboolean clutter_actor_box_contains (const ClutterActorBox *box,
gfloat x,
gfloat y);
CLUTTER_EXPORT
void clutter_actor_box_from_vertices (ClutterActorBox *box,
const graphene_point3d_t verts[]);
void clutter_actor_box_from_vertices (ClutterActorBox *box,
const ClutterVertex verts[]);
CLUTTER_EXPORT
void clutter_actor_box_interpolate (const ClutterActorBox *initial,
const ClutterActorBox *final,
@@ -257,6 +571,41 @@ CLUTTER_EXPORT
void clutter_actor_box_scale (ClutterActorBox *box,
gfloat scale);
/**
* 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_EXPORT
GType clutter_geometry_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
void clutter_geometry_union (const ClutterGeometry *geometry_a,
const ClutterGeometry *geometry_b,
ClutterGeometry *result);
CLUTTER_DEPRECATED
gboolean clutter_geometry_intersects (const ClutterGeometry *geometry0,
const ClutterGeometry *geometry1);
/**
* ClutterKnot:
* @x: X coordinate of the knot
@@ -328,10 +677,10 @@ void clutter_paint_volume_free (ClutterPaintVolume
CLUTTER_EXPORT
void clutter_paint_volume_set_origin (ClutterPaintVolume *pv,
const graphene_point3d_t *origin);
const ClutterVertex *origin);
CLUTTER_EXPORT
void clutter_paint_volume_get_origin (const ClutterPaintVolume *pv,
graphene_point3d_t *vertex);
ClutterVertex *vertex);
CLUTTER_EXPORT
void clutter_paint_volume_set_width (ClutterPaintVolume *pv,
gfloat width);

View File

@@ -51,8 +51,8 @@ void
_clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
const CoglMatrix *projection,
const float *viewport,
const graphene_point3d_t *vertices_in,
graphene_point3d_t *vertices_out,
const ClutterVertex *vertices_in,
ClutterVertex *vertices_out,
int n_vertices)
{
CoglMatrix modelview_projection;
@@ -69,7 +69,7 @@ _clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
modelview);
cogl_matrix_project_points (&modelview_projection,
3,
sizeof (graphene_point3d_t),
sizeof (ClutterVertex),
vertices_in,
sizeof (ClutterVertex4),
vertices_tmp,
@@ -79,7 +79,7 @@ _clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
{
cogl_matrix_transform_points (modelview,
3,
sizeof (graphene_point3d_t),
sizeof (ClutterVertex),
vertices_in,
sizeof (ClutterVertex4),
vertices_tmp,
@@ -97,7 +97,7 @@ _clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
for (i = 0; i < n_vertices; i++)
{
ClutterVertex4 vertex_tmp = vertices_tmp[i];
graphene_point3d_t *vertex_out = &vertices_out[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]);
@@ -108,9 +108,9 @@ _clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
void
_clutter_util_rect_from_rectangle (const cairo_rectangle_int_t *src,
graphene_rect_t *dest)
ClutterRect *dest)
{
*dest = (graphene_rect_t) {
*dest = (ClutterRect) {
.origin = {
.x = src->x,
.y = src->y
@@ -123,12 +123,12 @@ _clutter_util_rect_from_rectangle (const cairo_rectangle_int_t *src,
}
void
_clutter_util_rectangle_int_extents (const graphene_rect_t *src,
_clutter_util_rectangle_int_extents (const ClutterRect *src,
cairo_rectangle_int_t *dest)
{
graphene_rect_t tmp = *src;
ClutterRect tmp = *src;
graphene_rect_round_extents (&tmp, &tmp);
clutter_rect_clamp_to_pixel (&tmp);
*dest = (cairo_rectangle_int_t) {
.x = tmp.origin.x,
@@ -299,12 +299,48 @@ _clutter_util_matrix_skew_yz (ClutterMatrix *matrix,
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_combine (const graphene_point3d_t *a,
const graphene_point3d_t *b,
double ascl,
double bscl,
graphene_point3d_t *res)
_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);
@@ -352,16 +388,16 @@ _clutter_util_vertex4_interpolate (const ClutterVertex4 *a,
*/
gboolean
_clutter_util_matrix_decompose (const ClutterMatrix *src,
graphene_point3d_t *scale_p,
ClutterVertex *scale_p,
float shear_p[3],
graphene_point3d_t *rotate_p,
graphene_point3d_t *translate_p,
ClutterVertex *rotate_p,
ClutterVertex *translate_p,
ClutterVertex4 *perspective_p)
{
CoglMatrix matrix = *src;
CoglMatrix perspective;
ClutterVertex4 vertex_tmp;
graphene_point3d_t row[3], pdum;
ClutterVertex row[3], pdum;
int i, j;
#define XY_SHEAR 0
@@ -449,34 +485,34 @@ _clutter_util_matrix_decompose (const ClutterMatrix *src,
}
/* compute scale.x and normalize the first row */
scale_p->x = graphene_point3d_length (&row[0]);
graphene_point3d_normalize (&row[0], &row[0]);
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] = graphene_point3d_dot (&row[0], &row[1]);
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 = graphene_point3d_length (&row[1]);
graphene_point3d_normalize (&row[1], &row[1]);
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] = graphene_point3d_dot (&row[0], &row[2]);
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] = graphene_point3d_dot (&row[1], &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 = graphene_point3d_length (&row[2]);
graphene_point3d_normalize (&row[2], &row[2]);
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;
@@ -484,8 +520,8 @@ _clutter_util_matrix_decompose (const ClutterMatrix *src,
* check for a coordinate system flip; if the determinant
* is -1, then negate the matrix and scaling factors
*/
graphene_point3d_cross (&row[1], &row[2], &pdum);
if (graphene_point3d_dot (&row[0], &pdum) < 0.f)
_clutter_util_vertex_cross (&row[1], &row[2], &pdum);
if (_clutter_util_vertex_dot (&row[0], &pdum) < 0.f)
{
scale_p->x *= -1.f;

View File

@@ -80,9 +80,9 @@ struct _ClutterZoomActionPrivate
ZoomPoint points[2];
graphene_point_t initial_focal_point;
graphene_point_t focal_point;
graphene_point_t transformed_focal_point;
ClutterPoint initial_focal_point;
ClutterPoint focal_point;
ClutterPoint transformed_focal_point;
gfloat initial_x;
gfloat initial_y;
@@ -238,13 +238,13 @@ clutter_zoom_action_gesture_cancel (ClutterGestureAction *action,
static gboolean
clutter_zoom_action_real_zoom (ClutterZoomAction *action,
ClutterActor *actor,
graphene_point_t *focal_point,
ClutterPoint *focal_point,
gdouble factor)
{
ClutterZoomActionPrivate *priv = action->priv;
gfloat x, y, z;
gdouble scale_x, scale_y;
graphene_point3d_t out, in;
ClutterVertex out, in;
in.x = priv->transformed_focal_point.x;
in.y = priv->transformed_focal_point.y;
@@ -400,7 +400,7 @@ clutter_zoom_action_class_init (ClutterZoomActionClass *klass)
_clutter_marshal_BOOLEAN__OBJECT_BOXED_DOUBLE,
G_TYPE_BOOLEAN, 3,
CLUTTER_TYPE_ACTOR,
GRAPHENE_TYPE_POINT,
CLUTTER_TYPE_POINT,
G_TYPE_DOUBLE);
}
@@ -478,7 +478,7 @@ clutter_zoom_action_get_zoom_axis (ClutterZoomAction *action)
/**
* clutter_zoom_action_get_focal_point:
* @action: a #ClutterZoomAction
* @point: (out): a #graphene_point_t
* @point: (out): a #ClutterPoint
*
* Retrieves the focal point of the current zoom
*
@@ -486,7 +486,7 @@ clutter_zoom_action_get_zoom_axis (ClutterZoomAction *action)
*/
void
clutter_zoom_action_get_focal_point (ClutterZoomAction *action,
graphene_point_t *point)
ClutterPoint *point)
{
g_return_if_fail (CLUTTER_IS_ZOOM_ACTION (action));
g_return_if_fail (point != NULL);
@@ -497,7 +497,7 @@ clutter_zoom_action_get_focal_point (ClutterZoomAction *action,
/**
* clutter_zoom_action_get_transformed_focal_point:
* @action: a #ClutterZoomAction
* @point: (out): a #graphene_point_t
* @point: (out): a #ClutterPoint
*
* Retrieves the focal point relative to the actor's coordinates of
* the current zoom
@@ -506,7 +506,7 @@ clutter_zoom_action_get_focal_point (ClutterZoomAction *action,
*/
void
clutter_zoom_action_get_transformed_focal_point (ClutterZoomAction *action,
graphene_point_t *point)
ClutterPoint *point)
{
g_return_if_fail (CLUTTER_IS_ZOOM_ACTION (action));
g_return_if_fail (point != NULL);

View File

@@ -79,7 +79,7 @@ struct _ClutterZoomActionClass
/*< public >*/
gboolean (* zoom) (ClutterZoomAction *action,
ClutterActor *actor,
graphene_point_t *focal_point,
ClutterPoint *focal_point,
gdouble factor);
/*< private >*/
@@ -104,10 +104,10 @@ ClutterZoomAxis clutter_zoom_action_get_zoom_axis (ClutterZoomActi
CLUTTER_EXPORT
void clutter_zoom_action_get_focal_point (ClutterZoomAction *action,
graphene_point_t *point);
ClutterPoint *point);
CLUTTER_EXPORT
void clutter_zoom_action_get_transformed_focal_point (ClutterZoomAction *action,
graphene_point_t *point);
ClutterPoint *point);
G_END_DECLS

View File

@@ -526,11 +526,7 @@ paint_stage (ClutterStageCogl *stage_cogl,
_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);
}
clutter_stage_view_blit_offscreen (view, clip);
}
static void
@@ -625,14 +621,14 @@ is_buffer_age_enabled (void)
}
static void
scale_and_clamp_rect (const graphene_rect_t *rect,
scale_and_clamp_rect (const ClutterRect *rect,
float scale,
cairo_rectangle_int_t *dest)
{
graphene_rect_t tmp = *rect;
ClutterRect tmp = *rect;
graphene_rect_scale (&tmp, scale, scale, &tmp);
clutter_rect_scale (&tmp, scale, scale);
_clutter_util_rectangle_int_extents (&tmp, dest);
}
@@ -699,12 +695,12 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
* frames when starting up... */
cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3)
{
graphene_rect_t rect;
ClutterRect rect;
may_use_clipped_redraw = TRUE;
_clutter_util_rect_from_rectangle (&redraw_clip, &rect);
graphene_rect_offset (&rect, -view_rect.x, -view_rect.y);
clutter_rect_offset (&rect, -view_rect.x, -view_rect.y);
scale_and_clamp_rect (&rect, fb_scale, &fb_clip_region);
if (fb_scale != floorf (fb_scale))
@@ -742,7 +738,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
if (valid_buffer_age (view_cogl, age))
{
graphene_rect_t rect;
ClutterRect rect;
cairo_rectangle_int_t damage_region;
*current_fb_damage = fb_clip_region;
@@ -802,7 +798,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
}
else if (use_clipped_redraw)
{
graphene_rect_t rect;
ClutterRect rect;
cairo_rectangle_int_t scissor_rect;
cairo_rectangle_int_t paint_rect;
@@ -848,7 +844,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
may_use_clipped_redraw &&
!clip_region_empty)
{
graphene_rect_t rect;
ClutterRect rect;
cairo_rectangle_int_t scissor_rect;
cairo_rectangle_int_t paint_rect;

View File

@@ -0,0 +1,44 @@
#include "clutter-build-config.h"
#include <glib-object.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-actor.h"
#include "clutter-actor-private.h"
#include "clutter-private.h"
/**
* 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));
}

View File

@@ -145,6 +145,10 @@ CLUTTER_DEPRECATED
void clutter_actor_get_transformation_matrix (ClutterActor *self,
ClutterMatrix *matrix);
CLUTTER_DEPRECATED_FOR (clutter_actor_get_allocation_box)
void clutter_actor_get_allocation_geometry (ClutterActor *self,
ClutterGeometry *geom);
G_END_DECLS
#endif /* __CLUTTER_ACTOR_DEPRECATED_H__ */

View File

@@ -2220,7 +2220,7 @@ clutter_actor_animate_with_timeline (ClutterActor *actor,
*
* 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 #graphene_point3d_t "center".
* 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

View File

@@ -294,7 +294,7 @@ clutter_cairo_texture_context_destroy (void *data)
cogl_texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (cairo));
if (cairo_width == 0 ||
cairo_height == 0 ||
cogl_texture == NULL)
cogl_texture == COGL_INVALID_HANDLE)
{
draw_context_destroy (ctxt);
return;
@@ -507,7 +507,7 @@ clutter_cairo_texture_create_surface (ClutterCairoTexture *self,
cairo_stride,
cairo_data);
clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (self), cogl_texture);
cogl_object_unref (cogl_texture);
cogl_handle_unref (cogl_texture);
return surface;
}

View File

@@ -65,6 +65,16 @@ void clutter_container_remove_valist (ClutterContaine
CLUTTER_DEPRECATED_FOR(clutter_actor_get_children)
GList * clutter_container_get_children (ClutterContainer *container);
CLUTTER_DEPRECATED
void clutter_container_foreach (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data);
CLUTTER_DEPRECATED
void clutter_container_foreach_with_internals (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_child_above_sibling)
void clutter_container_raise_child (ClutterContainer *container,
ClutterActor *actor,

View File

@@ -170,6 +170,20 @@ clutter_group_real_actor_removed (ClutterContainer *container,
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,
@@ -271,6 +285,7 @@ clutter_container_iface_init (ClutterContainerIface *iface)
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;
@@ -291,12 +306,13 @@ clutter_group_real_paint (ClutterActor *actor)
}
static void
clutter_group_real_pick (ClutterActor *actor)
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);
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor, pick);
g_list_foreach (priv->children, (GFunc) clutter_actor_paint, NULL);
}
@@ -375,28 +391,21 @@ clutter_group_dispose (GObject *object)
}
static void
clutter_group_real_show_all (ClutterActor *self)
clutter_group_real_show_all (ClutterActor *actor)
{
ClutterActorIter iter;
ClutterActor *actor;
clutter_actor_iter_init (&iter, self);
while (clutter_actor_iter_next (&iter, &actor))
clutter_actor_show (actor);
clutter_actor_show (self);
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)
{
ClutterActorIter iter;
clutter_actor_hide (actor);
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &actor))
clutter_actor_hide (actor);
clutter_container_foreach (CLUTTER_CONTAINER (actor),
CLUTTER_CALLBACK (clutter_actor_hide),
NULL);
}
static gboolean

View File

@@ -84,7 +84,7 @@ clutter_rectangle_paint (ClutterActor *self)
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
static CoglPipeline *default_color_pipeline = NULL;
CoglPipeline *content_pipeline;
ClutterActorBox alloc;
ClutterGeometry geom;
CoglColor color;
guint8 tmp_alpha;
@@ -92,7 +92,7 @@ clutter_rectangle_paint (ClutterActor *self)
"painting rect '%s'",
clutter_actor_get_name (self) ? clutter_actor_get_name (self)
: "unknown");
clutter_actor_get_allocation_box (self, &alloc);
clutter_actor_get_allocation_geometry (self, &geom);
if (G_UNLIKELY (default_color_pipeline == NULL))
{
@@ -140,41 +140,40 @@ clutter_rectangle_paint (ClutterActor *self)
/* We paint the border and the content only if the rectangle
* is big enough to show them
*/
if ((priv->border_width * 2) < clutter_actor_box_get_width (&alloc) &&
(priv->border_width * 2) < clutter_actor_box_get_height (&alloc))
if ((priv->border_width * 2) < geom.width &&
(priv->border_width * 2) < geom.height)
{
/* paint the border. this sucks, but it's the only way to make a border */
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
priv->border_width, 0,
clutter_actor_box_get_width (&alloc),
geom.width,
priv->border_width);
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
clutter_actor_box_get_width (&alloc) - priv->border_width,
geom.width - priv->border_width,
priv->border_width,
clutter_actor_box_get_width (&alloc),
clutter_actor_box_get_height (&alloc));
geom.width, geom.height);
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
0, clutter_actor_box_get_height (&alloc) - priv->border_width,
clutter_actor_box_get_width (&alloc) - priv->border_width,
clutter_actor_box_get_height (&alloc));
0, geom.height - priv->border_width,
geom.width - priv->border_width,
geom.height);
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
0, 0,
priv->border_width,
clutter_actor_box_get_height (&alloc) - priv->border_width);
geom.height - priv->border_width);
/* now paint the rectangle */
cogl_framebuffer_draw_rectangle (framebuffer,
content_pipeline,
priv->border_width, priv->border_width,
clutter_actor_box_get_width (&alloc) - priv->border_width,
clutter_actor_box_get_height (&alloc) - priv->border_width);
geom.width - priv->border_width,
geom.height - priv->border_width);
}
else
{
@@ -184,9 +183,7 @@ clutter_rectangle_paint (ClutterActor *self)
*/
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
0, 0,
clutter_actor_box_get_width (&alloc),
clutter_actor_box_get_height (&alloc));
0, 0, geom.width, geom.height);
}
cogl_object_unref (border_pipeline);
@@ -195,9 +192,7 @@ clutter_rectangle_paint (ClutterActor *self)
{
cogl_framebuffer_draw_rectangle (framebuffer,
content_pipeline,
0, 0,
clutter_actor_box_get_width (&alloc),
clutter_actor_box_get_height (&alloc));
0, 0, geom.width, geom.height);
}
cogl_object_unref (content_pipeline);

View File

@@ -74,6 +74,20 @@ gboolean clutter_stage_is_default (ClutterStage *stage);
CLUTTER_DEPRECATED_FOR(clutter_actor_queue_redraw)
void clutter_stage_queue_redraw (ClutterStage *stage);
CLUTTER_DEPRECATED
void clutter_stage_set_use_fog (ClutterStage *stage,
gboolean fog);
CLUTTER_DEPRECATED
gboolean clutter_stage_get_use_fog (ClutterStage *stage);
CLUTTER_DEPRECATED
void clutter_stage_set_fog (ClutterStage *stage,
ClutterFog *fog);
CLUTTER_DEPRECATED
void clutter_stage_get_fog (ClutterStage *stage,
ClutterFog *fog);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color)
void clutter_stage_set_color (ClutterStage *stage,

View File

@@ -438,7 +438,7 @@ set_viewport_with_buffer_under_fbo_source (ClutterActor *fbo_source,
* falling back to a stage sized fbo with an offset of (0,0)
*/
graphene_point3d_t verts[4];
ClutterVertex verts[4];
float x_min = G_MAXFLOAT, y_min = G_MAXFLOAT;
int i;
@@ -1229,7 +1229,7 @@ clutter_texture_get_cogl_material (ClutterTexture *texture)
* 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_object_unref. Texture data is attached to the material so
* 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
@@ -1302,7 +1302,7 @@ get_first_layer_index (CoglPipeline *pipeline, int *layer_index)
*
* 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_object_ref() on it.
* 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
@@ -1342,7 +1342,7 @@ clutter_texture_get_cogl_texture (ClutterTexture *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_object_unref.
* no longer needed it should be deref'd with cogl_handle_unref.
*
* Since: 0.8
*

View File

@@ -127,7 +127,6 @@ clutter_sources = [
'clutter-flatten-effect.c',
'clutter-flow-layout.c',
'clutter-gesture-action.c',
'clutter-graphene.c',
'clutter-grid-layout.c',
'clutter-image.c',
'clutter-input-device.c',
@@ -192,7 +191,6 @@ clutter_private_headers = [
'clutter-effect-private.h',
'clutter-event-private.h',
'clutter-flatten-effect.h',
'clutter-graphene.h',
'clutter-gesture-action-private.h',
'clutter-id-pool.h',
'clutter-input-focus-private.h',
@@ -242,6 +240,7 @@ clutter_deprecated_headers = [
]
clutter_deprecated_sources = [
'deprecated/clutter-actor-deprecated.c',
'deprecated/clutter-alpha.c',
'deprecated/clutter-animation.c',
'deprecated/clutter-behaviour.c',
@@ -455,7 +454,6 @@ libmutter_clutter = shared_library(libmutter_clutter_name,
libmutter_clutter_dep = declare_dependency(
sources: [clutter_enum_types[1]],
link_with: libmutter_clutter,
dependencies: clutter_deps,
)
if have_introspection

View File

@@ -938,12 +938,11 @@ cogl_atlas_texture_new_from_data (CoglContext *ctx,
CoglAtlasTexture *atlas_tex;
g_return_val_if_fail (format != COGL_PIXEL_FORMAT_ANY, NULL);
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, NULL);
g_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, 0);
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format);
/* Wrap the data into a bitmap */
bmp = cogl_bitmap_new_for_data (ctx,

View File

@@ -182,8 +182,6 @@ _cogl_atlas_get_initial_size (CoglPixelFormat format,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
g_return_if_fail (cogl_pixel_format_get_n_planes (format) == 1);
ctx->driver_vtable->pixel_format_to_gl (ctx,
format,
&gl_intformat,
@@ -195,7 +193,7 @@ _cogl_atlas_get_initial_size (CoglPixelFormat format,
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, 0) == 1)
if (_cogl_pixel_format_get_bytes_per_pixel (format) == 1)
size = 1024;
else
size = 512;
@@ -289,16 +287,11 @@ _cogl_atlas_create_texture (CoglAtlas *atlas,
_COGL_GET_CONTEXT (ctx, NULL);
g_return_val_if_fail (
cogl_pixel_format_get_n_planes (atlas->texture_format) == 1,
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,
0);
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);

View File

@@ -652,6 +652,7 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
* 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)) &&

View File

@@ -135,10 +135,8 @@ _cogl_bitmap_copy_subregion (CoglBitmap *src,
g_return_val_if_fail ((src->format & ~COGL_PREMULT_BIT) ==
(dst->format & ~COGL_PREMULT_BIT),
FALSE);
g_return_val_if_fail (cogl_pixel_format_get_n_planes (src->format) == 1,
FALSE);
bpp = cogl_pixel_format_get_bytes_per_pixel (src->format, 0);
bpp = _cogl_pixel_format_get_bytes_per_pixel (src->format);
if ((srcdata = _cogl_bitmap_map (src, COGL_BUFFER_ACCESS_READ, 0, error)))
{
@@ -185,11 +183,10 @@ cogl_bitmap_new_for_data (CoglContext *context,
CoglBitmap *bmp;
g_return_val_if_fail (cogl_is_context (context), NULL);
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, NULL);
/* Rowstride from width if not given */
if (rowstride == 0)
rowstride = width * cogl_pixel_format_get_bytes_per_pixel (format, 0);
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format);
bmp = g_slice_new (CoglBitmap);
bmp->context = context;
@@ -214,18 +211,11 @@ _cogl_bitmap_new_with_malloc_buffer (CoglContext *context,
GError **error)
{
static CoglUserDataKey bitmap_free_key;
int bpp;
int rowstride;
uint8_t *data;
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;
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, NULL);
/* Try to malloc the data */
bpp = cogl_pixel_format_get_bytes_per_pixel (format, 0);
rowstride = ((width * bpp) + 3) & ~3;
data = g_try_malloc (rowstride * height);
if (!data)
{
g_set_error_literal (error, COGL_SYSTEM_ERROR,
@@ -234,7 +224,6 @@ _cogl_bitmap_new_with_malloc_buffer (CoglContext *context,
return NULL;
}
/* Now create the bitmap */
bitmap = cogl_bitmap_new_for_data (context,
width, height,
format,
@@ -316,11 +305,10 @@ cogl_bitmap_new_with_size (CoglContext *context,
/* creating a buffer to store "any" format does not make sense */
g_return_val_if_fail (format != COGL_PIXEL_FORMAT_ANY, NULL);
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, 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, 0);
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format);
pixel_buffer =
cogl_pixel_buffer_new (context,

View File

@@ -276,11 +276,7 @@ static gboolean
_cogl_blit_get_tex_data_begin (CoglBlitData *data)
{
data->format = _cogl_texture_get_format (data->src_tex);
g_return_val_if_fail (cogl_pixel_format_get_n_planes (data->format) == 1,
FALSE);
data->bpp = cogl_pixel_format_get_bytes_per_pixel (data->format, 0);
data->bpp = _cogl_pixel_format_get_bytes_per_pixel (data->format);
data->image_data = g_malloc (data->bpp * data->src_width *
data->src_height);

View File

@@ -147,6 +147,8 @@ struct _CoglContext
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 */

View File

@@ -262,6 +262,8 @@ cogl_context_new (CoglDisplay *display,
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);
@@ -430,7 +432,7 @@ _cogl_context_free (CoglContext *context)
_cogl_free_framebuffer_stack (context->framebuffer_stack);
if (context->current_path)
cogl_object_unref (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);

196
cogl/cogl/cogl-euler.c Normal file
View File

@@ -0,0 +1,196 @@
/*
* 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 <robert@linux.intel.com>
*/
#include "cogl-config.h"
#include <cogl-util.h>
#include <cogl-euler.h>
#include <cogl-matrix.h>
#include "cogl-gtype-private.h"
#include <math.h>
#include <string.h>
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;
}
gboolean
cogl_euler_equal (const void *v1, const void *v2)
{
const CoglEuler *a = v1;
const CoglEuler *b = v2;
g_return_val_if_fail (v1 != NULL, FALSE);
g_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);
}

265
cogl/cogl/cogl-euler.h Normal file
View File

@@ -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 <robert@linux.intel.com>
*/
#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION)
#error "Only <cogl/cogl.h> can be included directly."
#endif
#ifndef __COGL_EULER_H
#define __COGL_EULER_H
#include <cogl/cogl-types.h>
#include <glib-object.h>
G_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:
* <itemizedlist>
* <listitem>
* Easy to understand and use, compared to quaternions and matrices,
* so may be a good choice for a user interface.
* </listitem>
* <listitem>
* Efficient storage, needing only 3 components any rotation can be
* represented.
* <note>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.</note>
* </listitem>
* </itemizedlist>
*
* Disadvantages:
* <itemizedlist>
* <listitem>
* Aliasing: it's possible to represent some rotations with multiple
* different heading, pitch and roll rotations.
* </listitem>
* <listitem>
* 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.
* </listitem>
* <listitem>
* 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.
* </listitem>
* <listitem>
* 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".
* </listitem>
* </itemizedlist>
*
* 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.
*
* <note>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.</note>
*
* 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.
*
* <note>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</note>
*
* Returns: %TRUE if @v1 and @v2 are equal else %FALSE.
* Since: 2.0
*/
gboolean
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);
G_END_DECLS
#endif /* __COGL_EULER_H */

View File

@@ -181,6 +181,10 @@ struct _CoglFramebuffer
int clear_clip_y1;
gboolean clear_clip_dirty;
/* Whether something has been drawn to the buffer since the last
* swap buffers or swap region. */
gboolean mid_scene;
/* driver specific */
gboolean dirty_bitmasks;
CoglFramebufferBits bits;
@@ -265,6 +269,9 @@ _cogl_framebuffer_clear_without_flush4f (CoglFramebuffer *framebuffer,
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
@@ -407,11 +414,6 @@ _cogl_framebuffer_try_creating_gl_fbo (CoglContext *ctx,
CoglOffscreenAllocateFlags flags,
CoglGLFramebuffer *gl_framebuffer);
void
cogl_framebuffer_set_viewport4fv (CoglFramebuffer *framebuffer,
float *viewport);
unsigned long
_cogl_framebuffer_compare (CoglFramebuffer *a,
CoglFramebuffer *b,

View File

@@ -241,6 +241,12 @@ _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,
@@ -250,16 +256,11 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
float alpha)
{
CoglClipStack *clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer);
gboolean had_depth_and_color_buffer_bits;
int scissor_x0;
int scissor_y0;
int scissor_x1;
int scissor_y1;
had_depth_and_color_buffer_bits =
(buffers & COGL_BUFFER_BIT_DEPTH) &&
(buffers & COGL_BUFFER_BIT_COLOR);
if (!framebuffer->depth_buffer_clear_needed &&
(buffers & COGL_BUFFER_BIT_DEPTH))
buffers &= ~(COGL_BUFFER_BIT_DEPTH);
@@ -305,7 +306,8 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
* Note: Comparing without an epsilon is considered
* appropriate here.
*/
if (had_depth_and_color_buffer_bits &&
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 &&
@@ -375,12 +377,13 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
cleared:
_cogl_framebuffer_mark_mid_scene (framebuffer);
_cogl_framebuffer_mark_clear_clip_dirty (framebuffer);
if (buffers & COGL_BUFFER_BIT_DEPTH)
framebuffer->depth_buffer_clear_needed = FALSE;
if (had_depth_and_color_buffer_bits)
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
@@ -394,11 +397,18 @@ cleared:
/* NB: A clear may be scissored so we need to track the extents
* that the clear is applicable too... */
_cogl_clip_stack_get_bounds (clip_stack,
&framebuffer->clear_clip_x0,
&framebuffer->clear_clip_y0,
&framebuffer->clear_clip_x1,
&framebuffer->clear_clip_y1);
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 */
}
}
}
@@ -474,23 +484,6 @@ _cogl_framebuffer_set_clip_stack (CoglFramebuffer *framebuffer,
framebuffer->clip_stack = stack;
}
void
cogl_framebuffer_set_viewport4fv (CoglFramebuffer *framebuffer,
float *viewport)
{
if (framebuffer->viewport_x == viewport[0] &&
framebuffer->viewport_y == viewport[1] &&
framebuffer->viewport_width == viewport[2] &&
framebuffer->viewport_height == viewport[3])
return;
framebuffer->viewport_x = viewport[0];
framebuffer->viewport_y = viewport[1];
framebuffer->viewport_width = viewport[2];
framebuffer->viewport_height = viewport[3];
framebuffer->viewport_age++;
}
void
cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
float x,
@@ -498,6 +491,8 @@ cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
float width,
float height)
{
CoglContext *context = framebuffer->context;
g_return_if_fail (width > 0 && height > 0);
if (framebuffer->viewport_x == x &&
@@ -506,10 +501,16 @@ cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
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;
}
float
@@ -1055,7 +1056,12 @@ cogl_framebuffer_set_dither_enabled (CoglFramebuffer *framebuffer,
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
@@ -1310,13 +1316,10 @@ cogl_framebuffer_read_pixels (CoglFramebuffer *framebuffer,
CoglPixelFormat format,
uint8_t *pixels)
{
int bpp;
int bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
CoglBitmap *bitmap;
gboolean ret;
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, FALSE);
bpp = cogl_pixel_format_get_bytes_per_pixel (format, 0);
bitmap = cogl_bitmap_new_for_data (framebuffer->context,
width, height,
format,
@@ -1539,9 +1542,22 @@ cogl_framebuffer_rotate (CoglFramebuffer *framebuffer,
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 graphene_euler_t *euler)
const CoglEuler *euler)
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);

View File

@@ -52,11 +52,11 @@ typedef struct _CoglFramebuffer CoglFramebuffer;
#include <cogl/cogl-pipeline.h>
#include <cogl/cogl-indices.h>
#include <cogl/cogl-bitmap.h>
#include <cogl/cogl-quaternion.h>
#include <cogl/cogl-euler.h>
#include <cogl/cogl-texture.h>
#include <glib-object.h>
#include <graphene.h>
G_BEGIN_DECLS
/**
@@ -362,10 +362,25 @@ cogl_framebuffer_rotate (CoglFramebuffer *framebuffer,
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 #graphene_euler_t
* @euler: A #CoglEuler
*
* Multiplies the current model-view matrix by one that rotates
* according to the rotation described by @euler.
@@ -375,7 +390,7 @@ cogl_framebuffer_rotate (CoglFramebuffer *framebuffer,
*/
void
cogl_framebuffer_rotate_euler (CoglFramebuffer *framebuffer,
const graphene_euler_t *euler);
const CoglEuler *euler);
/**
* cogl_framebuffer_transform:

View File

@@ -78,8 +78,6 @@ typedef struct _CoglJournalEntry
CoglPipeline *pipeline;
CoglMatrixEntry *modelview_entry;
CoglClipStack *clip_stack;
float viewport[4];
gboolean dither_enabled;
/* Offset into ctx->logged_vertices */
size_t array_offset;
int n_layers;

View File

@@ -1044,98 +1044,6 @@ compare_entry_clip_stacks (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
return entry0->clip_stack == entry1->clip_stack;
}
static void
_cogl_journal_flush_dither_and_entries (CoglJournalEntry *batch_start,
int batch_len,
void *data)
{
CoglJournalFlushState *state = data;
CoglFramebuffer *framebuffer = state->journal->framebuffer;
CoglContext *ctx = framebuffer->context;
COGL_STATIC_TIMER (time_flush_dither_and_entries,
"Journal Flush", /* parent */
"flush: viewport+dither+clip+vbo+texcoords+pipeline+entries",
"The time spent flushing viewport + dither + clip + vbo + "
"texcoord offsets + pipeline + entries",
0 /* no application private data */);
COGL_TIMER_START (_cogl_uprof_context, time_flush_dither_and_entries);
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
g_print ("BATCHING: dither batch len = %d\n", batch_len);
cogl_framebuffer_set_dither_enabled (framebuffer, batch_start->dither_enabled);
ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_DITHER;
_cogl_framebuffer_flush_state (framebuffer,
framebuffer,
COGL_FRAMEBUFFER_STATE_DITHER);
batch_and_call (batch_start,
batch_len,
compare_entry_clip_stacks,
_cogl_journal_flush_clip_stacks_and_entries,
state);
COGL_TIMER_STOP (_cogl_uprof_context, time_flush_dither_and_entries);
}
static gboolean
compare_entry_dither_states (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
{
return entry0->dither_enabled == entry1->dither_enabled;
}
static void
_cogl_journal_flush_viewport_and_entries (CoglJournalEntry *batch_start,
int batch_len,
void *data)
{
CoglJournalFlushState *state = data;
CoglFramebuffer *framebuffer = state->journal->framebuffer;
CoglContext *ctx = framebuffer->context;
float current_viewport[4];
COGL_STATIC_TIMER (time_flush_viewport_and_entries,
"Journal Flush", /* parent */
"flush: viewport+clip+vbo+texcoords+pipeline+entries",
"The time spent flushing viewport + clip + vbo + texcoord offsets + "
"pipeline + entries",
0 /* no application private data */);
COGL_TIMER_START (_cogl_uprof_context, time_flush_viewport_and_entries);
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
g_print ("BATCHING: viewport batch len = %d\n", batch_len);
ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_VIEWPORT;
cogl_framebuffer_get_viewport4fv (framebuffer, current_viewport);
cogl_framebuffer_set_viewport4fv (framebuffer, batch_start->viewport);
_cogl_framebuffer_flush_state (framebuffer,
framebuffer,
COGL_FRAMEBUFFER_STATE_VIEWPORT);
batch_and_call (batch_start,
batch_len,
compare_entry_dither_states,
_cogl_journal_flush_dither_and_entries,
state);
if (memcmp (batch_start->viewport, current_viewport, sizeof (float) * 4) != 0)
cogl_framebuffer_set_viewport4fv (framebuffer, current_viewport);
COGL_TIMER_STOP (_cogl_uprof_context, time_flush_viewport_and_entries);
}
static gboolean
compare_entry_viewports (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
{
return memcmp (entry0->viewport, entry1->viewport, sizeof (float) * 4) == 0;
}
/* 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 *
@@ -1423,14 +1331,12 @@ _cogl_journal_flush (CoglJournal *journal)
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 viewport, the modelview
* stack and clip state manually */
/* 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_DITHER |
COGL_FRAMEBUFFER_STATE_VIEWPORT |
COGL_FRAMEBUFFER_STATE_MODELVIEW |
~(COGL_FRAMEBUFFER_STATE_MODELVIEW |
COGL_FRAMEBUFFER_STATE_CLIP));
/* We need to mark the current modelview state of the framebuffer as
@@ -1489,11 +1395,11 @@ _cogl_journal_flush (CoglJournal *journal)
* 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,
journal->entries->len,
compare_entry_viewports,
_cogl_journal_flush_viewport_and_entries,
&state);
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));
@@ -1555,6 +1461,12 @@ _cogl_journal_log_quad (CoglJournal *journal,
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 */
@@ -1640,9 +1552,6 @@ _cogl_journal_log_quad (CoglJournal *journal,
clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer);
entry->clip_stack = _cogl_clip_stack_ref (clip_stack);
entry->dither_enabled = cogl_framebuffer_get_dither_enabled (framebuffer);
cogl_framebuffer_get_viewport4fv (framebuffer, entry->viewport);
if (G_UNLIKELY (final_pipeline != pipeline))
cogl_object_unref (final_pipeline);
@@ -1673,7 +1582,7 @@ entry_to_screen_polygon (CoglFramebuffer *framebuffer,
CoglMatrix projection;
CoglMatrix modelview;
int i;
const float *viewport = entry->viewport;
float viewport[4];
poly[0] = vertices[0];
poly[1] = vertices[1];
@@ -1722,6 +1631,8 @@ entry_to_screen_polygon (CoglFramebuffer *framebuffer,
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. */

View File

@@ -45,6 +45,7 @@ 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,
@@ -68,7 +69,9 @@ typedef struct _CoglMatrixEntryTranslate
{
CoglMatrixEntry _parent_data;
graphene_point3d_t translate;
float x;
float y;
float z;
} CoglMatrixEntryTranslate;
@@ -77,7 +80,9 @@ typedef struct _CoglMatrixEntryRotate
CoglMatrixEntry _parent_data;
float angle;
graphene_vec3_t axis;
float x;
float y;
float z;
} CoglMatrixEntryRotate;
@@ -85,9 +90,22 @@ typedef struct _CoglMatrixEntryRotateEuler
{
CoglMatrixEntry _parent_data;
graphene_euler_t euler;
/* 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;
@@ -129,6 +147,7 @@ typedef union _CoglMatrixEntryFull
CoglMatrixEntryTranslate translate;
CoglMatrixEntryRotate rotate;
CoglMatrixEntryRotateEuler rotate_euler;
CoglMatrixEntryRotateQuaternion rotate_quaternion;
CoglMatrixEntryScale scale;
CoglMatrixEntryMultiply multiply;
CoglMatrixEntryLoad load;

View File

@@ -158,7 +158,9 @@ cogl_matrix_stack_translate (CoglMatrixStack *stack,
entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_TRANSLATE);
graphene_point3d_init (&entry->translate, x, y, z);
entry->x = x;
entry->y = y;
entry->z = z;
}
void
@@ -173,18 +175,38 @@ cogl_matrix_stack_rotate (CoglMatrixStack *stack,
entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_ROTATE);
entry->angle = angle;
graphene_vec3_init (&entry->axis, x, y, z);
entry->x = x;
entry->y = y;
entry->z = z;
}
void
cogl_matrix_stack_rotate_euler (CoglMatrixStack *stack,
const graphene_euler_t *euler)
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);
graphene_euler_init_from_euler (&entry->euler, euler);
entry->heading = euler->heading;
entry->pitch = euler->pitch;
entry->roll = euler->roll;
}
void
@@ -335,6 +357,7 @@ cogl_matrix_entry_unref (CoglMatrixEntry *entry)
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;
@@ -475,6 +498,7 @@ initialized:
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:
@@ -536,9 +560,9 @@ initialized:
CoglMatrixEntryTranslate *translate =
(CoglMatrixEntryTranslate *)children[i];
cogl_matrix_translate (matrix,
translate->translate.x,
translate->translate.y,
translate->translate.z);
translate->x,
translate->y,
translate->z);
continue;
}
case COGL_MATRIX_OP_ROTATE:
@@ -547,17 +571,31 @@ initialized:
(CoglMatrixEntryRotate *)children[i];
cogl_matrix_rotate (matrix,
rotate->angle,
graphene_vec3_get_x (&rotate->axis),
graphene_vec3_get_y (&rotate->axis),
graphene_vec3_get_z (&rotate->axis));
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,
&rotate->euler);
&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:
@@ -752,9 +790,9 @@ cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0,
translate = (CoglMatrixEntryTranslate *)node0;
*x = *x - translate->translate.x;
*y = *y - translate->translate.y;
*z = *z - translate->translate.z;
*x = *x - translate->x;
*y = *y - translate->y;
*z = *z - translate->z;
}
for (head1 = common_ancestor1->next; head1; head1 = head1->next)
{
@@ -767,9 +805,9 @@ cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0,
translate = (CoglMatrixEntryTranslate *)node1;
*x = *x + translate->translate.x;
*y = *y + translate->translate.y;
*z = *z + translate->translate.z;
*x = *x + translate->x;
*y = *y + translate->y;
*z = *z + translate->z;
}
return TRUE;
@@ -932,8 +970,9 @@ cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
/* 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 (!graphene_point3d_equal (&translate0->translate,
&translate1->translate))
if (translate0->x != translate1->x ||
translate0->y != translate1->y ||
translate0->z != translate1->z)
return FALSE;
}
break;
@@ -944,10 +983,24 @@ cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
CoglMatrixEntryRotate *rotate1 =
(CoglMatrixEntryRotate *)entry1;
if (rotate0->angle != rotate1->angle ||
!graphene_vec3_equal (&rotate0->axis, &rotate1->axis))
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 =
@@ -955,7 +1008,9 @@ cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
CoglMatrixEntryRotateEuler *rotate1 =
(CoglMatrixEntryRotateEuler *)entry1;
if (!graphene_euler_equal (&rotate0->euler, &rotate1->euler))
if (rotate0->heading != rotate1->heading ||
rotate0->pitch != rotate1->pitch ||
rotate0->roll != rotate1->roll)
return FALSE;
}
break;
@@ -1031,9 +1086,9 @@ cogl_debug_matrix_entry_print (CoglMatrixEntry *entry)
CoglMatrixEntryTranslate *translate =
(CoglMatrixEntryTranslate *)entry;
g_print (" TRANSLATE X=%f Y=%f Z=%f\n",
translate->translate.x,
translate->translate.y,
translate->translate.z);
translate->x,
translate->y,
translate->z);
continue;
}
case COGL_MATRIX_OP_ROTATE:
@@ -1042,9 +1097,20 @@ cogl_debug_matrix_entry_print (CoglMatrixEntry *entry)
(CoglMatrixEntryRotate *)entry;
g_print (" ROTATE ANGLE=%f X=%f Y=%f Z=%f\n",
rotate->angle,
graphene_vec3_get_x (&rotate->axis),
graphene_vec3_get_y (&rotate->axis),
graphene_vec3_get_z (&rotate->axis));
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:
@@ -1052,9 +1118,9 @@ cogl_debug_matrix_entry_print (CoglMatrixEntry *entry)
CoglMatrixEntryRotateEuler *rotate =
(CoglMatrixEntryRotateEuler *)entry;
g_print (" ROTATE EULER heading=%f pitch=%f roll=%f\n",
graphene_euler_get_y (&rotate->euler),
graphene_euler_get_x (&rotate->euler),
graphene_euler_get_z (&rotate->euler));
rotate->heading,
rotate->pitch,
rotate->roll);
continue;
}
case COGL_MATRIX_OP_SCALE:

View File

@@ -42,7 +42,6 @@
#include "cogl-matrix.h"
#include "cogl-context.h"
#include <graphene.h>
/**
* SECTION:cogl-matrix-stack
@@ -307,17 +306,29 @@ cogl_matrix_stack_rotate (CoglMatrixStack *stack,
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 #graphene_euler_t
* @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 graphene_euler_t *euler);
const CoglEuler *euler);
/**
* cogl_matrix_stack_multiply:

View File

@@ -73,8 +73,11 @@
#include <cogl-util.h>
#include <cogl-debug.h>
#include <cogl-quaternion.h>
#include <cogl-quaternion-private.h>
#include <cogl-matrix.h>
#include <cogl-matrix-private.h>
#include <cogl-quaternion-private.h>
#include <glib.h>
#include <math.h>
@@ -1355,9 +1358,19 @@ cogl_matrix_rotate (CoglMatrix *matrix,
_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 graphene_euler_t *euler)
const CoglEuler *euler)
{
CoglMatrix rotation_transform;
@@ -1722,14 +1735,56 @@ _cogl_matrix_init_from_matrix_without_inverse (CoglMatrix *matrix,
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 graphene_euler_t *euler)
const CoglEuler *euler)
{
/* Convert angles to radians */
float heading_rad = graphene_euler_get_y (euler) / 180.0f * G_PI;
float pitch_rad = graphene_euler_get_x (euler) / 180.0f * G_PI;
float roll_rad = graphene_euler_get_z (euler) / 180.0f * G_PI;
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);
@@ -2183,41 +2238,41 @@ cogl_matrix_look_at (CoglMatrix *matrix,
float world_up_z)
{
CoglMatrix tmp;
graphene_vec3_t forward;
graphene_vec3_t side;
graphene_vec3_t up;
float forward[3];
float side[3];
float up[3];
/* Get a unit viewing direction vector */
graphene_vec3_init (&forward,
object_x - eye_position_x,
object_y - eye_position_y,
object_z - eye_position_z);
graphene_vec3_normalize (&forward, &forward);
cogl_vector3_init (forward,
object_x - eye_position_x,
object_y - eye_position_y,
object_z - eye_position_z);
cogl_vector3_normalize (forward);
graphene_vec3_init (&up, world_up_x, world_up_y, world_up_z);
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. */
graphene_vec3_cross (&forward, &up, &side);
graphene_vec3_normalize (&side, &side);
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. */
graphene_vec3_cross (&side, &forward, &up);
cogl_vector3_cross_product (up, side, forward);
tmp.xx = graphene_vec3_get_x (&side);
tmp.yx = graphene_vec3_get_y (&side);
tmp.zx = graphene_vec3_get_z (&side);
tmp.xx = side[0];
tmp.yx = side[1];
tmp.zx = side[2];
tmp.wx = 0;
tmp.xy = graphene_vec3_get_x (&up);
tmp.yy = graphene_vec3_get_y (&up);
tmp.zy = graphene_vec3_get_z (&up);
tmp.xy = up[0];
tmp.yy = up[1];
tmp.zy = up[2];
tmp.wy = 0;
tmp.xz = -graphene_vec3_get_x (&forward);
tmp.yz = -graphene_vec3_get_y (&forward);
tmp.zz = -graphene_vec3_get_z (&forward);
tmp.xz = -forward[0];
tmp.yz = -forward[1];
tmp.zz = -forward[2];
tmp.wz = 0;
tmp.xw = 0;

View File

@@ -41,10 +41,9 @@
#include <cogl/cogl-types.h>
#include <cogl/cogl-macros.h>
#include <cogl/cogl-quaternion.h>
#include <glib-object.h>
#include <graphene.h>
G_BEGIN_DECLS
/**
@@ -197,19 +196,33 @@ cogl_matrix_rotate (CoglMatrix *matrix,
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 #graphene_euler_t.
* given #CoglEuler.
*
* Since: 2.0
*/
void
cogl_matrix_rotate_euler (CoglMatrix *matrix,
const graphene_euler_t *euler);
const CoglEuler *euler);
/**
* cogl_matrix_translate:
@@ -502,16 +515,27 @@ cogl_matrix_init_from_array (CoglMatrix *matrix,
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 #graphene_euler_t
* @euler: A #CoglEuler
*
* Initializes @matrix from a #graphene_euler_t rotation.
* Initializes @matrix from a #CoglEuler rotation.
*/
void
cogl_matrix_init_from_euler (CoglMatrix *matrix,
const graphene_euler_t *euler);
const CoglEuler *euler);
/**
* cogl_matrix_equal:

View File

@@ -253,7 +253,7 @@ cogl_##type_name##_ref (void *object) \
\
_COGL_OBJECT_DEBUG_REF (TypeName, object); \
\
cogl_object_ref (object); \
cogl_handle_ref (object); \
\
return object; \
} \
@@ -271,7 +271,7 @@ cogl_##type_name##_unref (void *object) \
\
_COGL_OBJECT_DEBUG_UNREF (TypeName, object); \
\
cogl_object_unref (object); \
cogl_handle_unref (object); \
}
#define COGL_OBJECT_DEFINE(TypeName, type_name) \

View File

@@ -52,6 +52,12 @@ cogl_object_ref (void *object)
return object;
}
CoglHandle
cogl_handle_ref (CoglHandle handle)
{
return cogl_object_ref (handle);
}
void
_cogl_object_default_unref (void *object)
{
@@ -109,6 +115,12 @@ cogl_object_unref (void *obj)
unref_func (obj);
}
void
cogl_handle_unref (CoglHandle handle)
{
cogl_object_unref (handle);
}
GType
cogl_handle_get_type (void)
{

View File

@@ -336,6 +336,7 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
}
onscreen->frame_counter++;
framebuffer->mid_scene = FALSE;
}
void
@@ -392,6 +393,7 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
}
onscreen->frame_counter++;
framebuffer->mid_scene = FALSE;
}
int

View File

@@ -83,6 +83,7 @@ typedef enum
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,
@@ -130,6 +131,8 @@ typedef enum _CoglPipelineState
1L<<COGL_PIPELINE_STATE_USER_SHADER_INDEX,
COGL_PIPELINE_STATE_DEPTH =
1L<<COGL_PIPELINE_STATE_DEPTH_INDEX,
COGL_PIPELINE_STATE_FOG =
1L<<COGL_PIPELINE_STATE_FOG_INDEX,
COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE =
1L<<COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE_INDEX,
COGL_PIPELINE_STATE_POINT_SIZE =
@@ -178,6 +181,7 @@ typedef enum _CoglPipelineState
COGL_PIPELINE_STATE_BLEND | \
COGL_PIPELINE_STATE_USER_SHADER | \
COGL_PIPELINE_STATE_DEPTH | \
COGL_PIPELINE_STATE_FOG | \
COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE | \
COGL_PIPELINE_STATE_POINT_SIZE | \
COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE | \
@@ -191,6 +195,7 @@ typedef enum _CoglPipelineState
COGL_PIPELINE_STATE_LIGHTING | \
COGL_PIPELINE_STATE_BLEND | \
COGL_PIPELINE_STATE_DEPTH | \
COGL_PIPELINE_STATE_FOG | \
COGL_PIPELINE_STATE_CULL_FACE | \
COGL_PIPELINE_STATE_UNIFORMS | \
COGL_PIPELINE_STATE_VERTEX_SNIPPETS | \
@@ -245,6 +250,16 @@ typedef struct
GLint blend_dst_factor_rgb;
} CoglPipelineBlendState;
typedef struct
{
gboolean enabled;
CoglColor color;
CoglFogMode mode;
float density;
float z_near;
float z_far;
} CoglPipelineFogState;
typedef struct
{
CoglPipelineCullFaceMode mode;
@@ -272,6 +287,7 @@ typedef struct
CoglPipelineBlendState blend_state;
CoglHandle user_program;
CoglDepthState depth_state;
CoglPipelineFogState fog_state;
float point_size;
unsigned int non_zero_point_size : 1;
unsigned int per_vertex_point_size : 1;
@@ -841,6 +857,9 @@ void
_cogl_pipeline_set_blend_enabled (CoglPipeline *pipeline,
CoglPipelineBlendEnable enable);
gboolean
_cogl_pipeline_get_fog_enabled (CoglPipeline *pipeline);
#ifdef COGL_DEBUG_ENABLED
void
_cogl_pipeline_set_static_breadcrumb (CoglPipeline *pipeline,

View File

@@ -49,6 +49,10 @@ _cogl_pipeline_has_non_layer_vertex_snippets (CoglPipeline *pipeline);
gboolean
_cogl_pipeline_has_non_layer_fragment_snippets (CoglPipeline *pipeline);
void
_cogl_pipeline_set_fog_state (CoglPipeline *pipeline,
const CoglPipelineFogState *fog_state);
gboolean
_cogl_pipeline_color_equal (CoglPipeline *authority0,
CoglPipeline *authority1);
@@ -73,6 +77,10 @@ gboolean
_cogl_pipeline_depth_state_equal (CoglPipeline *authority0,
CoglPipeline *authority1);
gboolean
_cogl_pipeline_fog_state_equal (CoglPipeline *authority0,
CoglPipeline *authority1);
gboolean
_cogl_pipeline_non_zero_point_size_equal (CoglPipeline *authority0,
CoglPipeline *authority1);
@@ -144,6 +152,10 @@ 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);

View File

@@ -176,6 +176,24 @@ _cogl_pipeline_depth_state_equal (CoglPipeline *authority0,
}
}
gboolean
_cogl_pipeline_fog_state_equal (CoglPipeline *authority0,
CoglPipeline *authority1)
{
CoglPipelineFogState *fog_state0 = &authority0->big_state->fog_state;
CoglPipelineFogState *fog_state1 = &authority1->big_state->fog_state;
if (fog_state0->enabled == fog_state1->enabled &&
cogl_color_equal (&fog_state0->color, &fog_state1->color) &&
fog_state0->mode == fog_state1->mode &&
fog_state0->density == fog_state1->density &&
fog_state0->z_near == fog_state1->z_near &&
fog_state0->z_far == fog_state1->z_far)
return TRUE;
else
return FALSE;
}
gboolean
_cogl_pipeline_non_zero_point_size_equal (CoglPipeline *authority0,
CoglPipeline *authority1)
@@ -1052,7 +1070,7 @@ cogl_pipeline_get_user_program (CoglPipeline *pipeline)
{
CoglPipeline *authority;
g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
g_return_val_if_fail (cogl_is_pipeline (pipeline), COGL_INVALID_HANDLE);
authority =
_cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_USER_SHADER);
@@ -1087,7 +1105,7 @@ cogl_pipeline_set_user_program (CoglPipeline *pipeline,
*/
_cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
if (program != NULL)
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
@@ -1112,11 +1130,11 @@ cogl_pipeline_set_user_program (CoglPipeline *pipeline,
_cogl_pipeline_prune_redundant_ancestry (pipeline);
}
if (program != NULL)
cogl_object_ref (program);
if (program != COGL_INVALID_HANDLE)
cogl_handle_ref (program);
if (authority == pipeline &&
pipeline->big_state->user_program != NULL)
cogl_object_unref (pipeline->big_state->user_program);
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;
@@ -1174,6 +1192,41 @@ cogl_pipeline_get_depth_state (CoglPipeline *pipeline,
*state = authority->big_state->depth_state;
}
void
_cogl_pipeline_set_fog_state (CoglPipeline *pipeline,
const CoglPipelineFogState *fog_state)
{
CoglPipelineState state = COGL_PIPELINE_STATE_FOG;
CoglPipeline *authority;
CoglPipelineFogState *current_fog_state;
g_return_if_fail (cogl_is_pipeline (pipeline));
authority = _cogl_pipeline_get_authority (pipeline, state);
current_fog_state = &authority->big_state->fog_state;
if (current_fog_state->enabled == fog_state->enabled &&
cogl_color_equal (&current_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)
@@ -1797,6 +1850,23 @@ _cogl_pipeline_hash_depth_state (CoglPipeline *authority,
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)

View File

@@ -578,7 +578,7 @@ cogl_pipeline_get_per_vertex_point_size (CoglPipeline *pipeline);
* 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 %NULL.
* Return value: (transfer none): The current user program or %COGL_INVALID_HANDLE.
*
* Since: 2.0
* Stability: Unstable

View File

@@ -182,7 +182,7 @@ _cogl_pipeline_init_default_pipeline (void)
blend_state->blend_src_factor_rgb = GL_ONE;
blend_state->blend_dst_factor_rgb = GL_ONE_MINUS_SRC_ALPHA;
big_state->user_program = NULL;
big_state->user_program = COGL_INVALID_HANDLE;
cogl_depth_state_init (&big_state->depth_state);
@@ -435,7 +435,7 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
if (pipeline->differences & COGL_PIPELINE_STATE_USER_SHADER &&
pipeline->big_state->user_program)
cogl_object_unref (pipeline->big_state->user_program);
cogl_handle_unref (pipeline->big_state->user_program);
if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
{
@@ -749,7 +749,7 @@ _cogl_pipeline_change_implies_transparency (CoglPipeline *pipeline,
*
* TODO: check that it isn't just a vertex shader!
*/
if (_cogl_pipeline_get_user_program (pipeline) != NULL)
if (_cogl_pipeline_get_user_program (pipeline) != COGL_INVALID_HANDLE)
return TRUE;
}
@@ -990,9 +990,9 @@ _cogl_pipeline_copy_differences (CoglPipeline *dest,
{
if (src->big_state->user_program)
big_state->user_program =
cogl_object_ref (src->big_state->user_program);
cogl_handle_ref (src->big_state->user_program);
else
big_state->user_program = NULL;
big_state->user_program = COGL_INVALID_HANDLE;
}
if (differences & COGL_PIPELINE_STATE_DEPTH)
@@ -1002,6 +1002,13 @@ _cogl_pipeline_copy_differences (CoglPipeline *dest,
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;
@@ -1117,6 +1124,13 @@ _cogl_pipeline_init_multi_property_sparse_state (CoglPipeline *pipeline,
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_CULL_FACE:
{
memcpy (&pipeline->big_state->cull_face_state,
@@ -2244,6 +2258,11 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
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]))
@@ -2377,6 +2396,18 @@ _cogl_pipeline_update_authority (CoglPipeline *pipeline,
}
}
gboolean
_cogl_pipeline_get_fog_enabled (CoglPipeline *pipeline)
{
CoglPipeline *authority;
g_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)
{
@@ -2527,7 +2558,7 @@ _cogl_pipeline_apply_legacy_state (CoglPipeline *pipeline)
/* 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) == NULL)
cogl_pipeline_get_user_program (pipeline) == COGL_INVALID_HANDLE)
cogl_pipeline_set_user_program (pipeline, ctx->current_program);
if (ctx->legacy_depth_test_enabled)
@@ -2538,6 +2569,9 @@ _cogl_pipeline_apply_legacy_state (CoglPipeline *pipeline)
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);
@@ -2685,6 +2719,8 @@ _cogl_pipeline_init_state_hash_functions (void)
_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] =
@@ -2702,7 +2738,7 @@ _cogl_pipeline_init_state_hash_functions (void)
{
/* So we get a big error if we forget to update this code! */
_COGL_STATIC_ASSERT (COGL_PIPELINE_STATE_SPARSE_COUNT == 16,
_COGL_STATIC_ASSERT (COGL_PIPELINE_STATE_SPARSE_COUNT == 17,
"Make sure to install a hash function for "
"newly added pipeline state and update assert "
"in _cogl_pipeline_init_state_hash_functions");

View File

@@ -41,254 +41,235 @@ typedef struct _CoglPixelFormatInfo
{
CoglPixelFormat cogl_format;
const char *format_str;
int bpp; /* Bytes per pixel */
int aligned; /* Aligned components? (-1 if n/a) */
uint8_t n_planes;
/* Per-plane information */
uint8_t bpp[COGL_PIXEL_FORMAT_MAX_PLANES]; /* Bytes per pixel */
} CoglPixelFormatInfo;
static const CoglPixelFormatInfo format_info_table[] = {
{
.cogl_format = COGL_PIXEL_FORMAT_ANY,
.format_str = "ANY",
.n_planes = 0,
.aligned = -1,
.bpp = { 0 },
.bpp = 0,
.aligned = -1
},
{
.cogl_format = COGL_PIXEL_FORMAT_A_8,
.format_str = "A_8",
.n_planes = 1,
.aligned = 1,
.bpp = { 1 },
.bpp = 1,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGB_565,
.format_str = "RGB_565",
.n_planes = 1,
.aligned = 0,
.bpp = { 2 },
.bpp = 2,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_4444,
.format_str = "RGBA_4444",
.n_planes = 1,
.aligned = 0,
.bpp = { 2 },
.bpp = 2,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_5551,
.format_str = "RGBA_5551",
.n_planes = 1,
.aligned = 0,
.bpp = { 2 },
.bpp = 2,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_YUV,
.format_str = "YUV",
.n_planes = 1,
.aligned = -1,
.bpp = { 0 },
.bpp = 0,
.aligned = -1
},
{
.cogl_format = COGL_PIXEL_FORMAT_G_8,
.format_str = "G_8",
.n_planes = 1,
.aligned = 1,
.bpp = { 1 },
.bpp = 1,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RG_88,
.format_str = "RG_88",
.n_planes = 1,
.aligned = 1,
.bpp = { 2 },
.bpp = 2,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGB_888,
.format_str = "RGB_888",
.n_planes = 1,
.aligned = 1,
.bpp = { 3 },
.bpp = 3,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGR_888,
.format_str = "BGR_888",
.n_planes = 1,
.aligned = 1,
.bpp = { 3 },
.bpp = 3,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_8888,
.format_str = "RGBA_8888",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGRA_8888,
.format_str = "BGRA_8888",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ARGB_8888,
.format_str = "ARGB_8888",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ABGR_8888,
.format_str = "ABGR_8888",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_1010102,
.format_str = "RGBA_1010102",
.n_planes = 1,
.aligned = 0,
.bpp = { 4 },
.bpp = 4,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGRA_1010102,
.format_str = "BGRA_1010102",
.n_planes = 1,
.aligned = 0,
.bpp = { 4 },
.bpp = 4,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010,
.format_str = "ARGB_2101010",
.n_planes = 1,
.aligned = 0,
.bpp = { 4 },
.bpp = 4,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010,
.format_str = "ABGR_2101010",
.n_planes = 1,
.aligned = 0,
.bpp = { 4 },
.bpp = 4,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE,
.format_str = "RGBA_8888_PRE",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE,
.format_str = "BGRA_8888_PRE",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE,
.format_str = "ARGB_8888_PRE",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ABGR_8888_PRE,
.format_str = "ABGR_8888_PRE",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_4444_PRE,
.format_str = "RGBA_4444_PRE",
.n_planes = 1,
.aligned = 0,
.bpp = { 2 },
.bpp = 2,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_5551_PRE,
.format_str = "RGBA_5551_PRE",
.n_planes = 1,
.aligned = 0,
.bpp = { 2 },
.bpp = 2,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_1010102_PRE,
.format_str = "RGBA_1010102_PRE",
.n_planes = 1,
.aligned = 0,
.bpp = { 4 },
.bpp = 4,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGRA_1010102_PRE,
.format_str = "BGRA_1010102_PRE",
.n_planes = 1,
.aligned = 0,
.bpp = { 4 },
.bpp = 4,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE,
.format_str = "ARGB_2101010_PRE",
.n_planes = 1,
.aligned = 0,
.bpp = { 4 },
.bpp = 4,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010_PRE,
.format_str = "ABGR_2101010_PRE",
.n_planes = 1,
.aligned = 0,
.bpp = { 4 },
.bpp = 4,
.aligned = 0
},
{
.cogl_format = COGL_PIXEL_FORMAT_DEPTH_16,
.format_str = "DEPTH_16",
.n_planes = 1,
.aligned = 1,
.bpp = { 2 },
.bpp = 2,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_DEPTH_32,
.format_str = "DEPTH_32",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8,
.format_str = "DEPTH_24_STENCIL_8",
.n_planes = 1,
.aligned = 1,
.bpp = { 4 },
.bpp = 4,
.aligned = 1
},
};
/*
* 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 plane)
_cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format)
{
size_t i;
for (i = 0; i < G_N_ELEMENTS (format_info_table); i++)
{
if (format_info_table[i].cogl_format == format)
{
g_return_val_if_fail (plane < format_info_table[i].n_planes, 0);
return format_info_table[i].bpp[plane];
}
return format_info_table[i].bpp;
}
g_assert_not_reached ();
}
/* Note: this also refers to the mapping defined above for
* cogl_pixel_format_get_bytes_per_pixel() */
* _cogl_pixel_format_get_bytes_per_pixel() */
gboolean
_cogl_pixel_format_is_endian_dependant (CoglPixelFormat format)
{
@@ -314,20 +295,6 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format)
return aligned;
}
int
cogl_pixel_format_get_n_planes (CoglPixelFormat format)
{
size_t i;
for (i = 0; i < G_N_ELEMENTS (format_info_table); i++)
{
if (format_info_table[i].cogl_format == format)
return format_info_table[i].n_planes;
}
g_assert_not_reached ();
}
const char *
cogl_pixel_format_to_string (CoglPixelFormat format)
{

View File

@@ -233,27 +233,17 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/
COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8 = (3 | COGL_DEPTH_BIT | COGL_STENCIL_BIT)
} CoglPixelFormat;
/**
* COGL_PIXEL_FORMAT_MAX_PLANES:
/*
* _cogl_pixel_format_get_bytes_per_pixel:
* @format: a #CoglPixelFormat
*
* The maximum number of planes of a pixel format (see also
* cogl_pixel_format_get_planes()).
*/
#define COGL_PIXEL_FORMAT_MAX_PLANES (4)
/**
* cogl_pixel_format_get_bytes_per_pixel:
* @format: The pixel format
* @plane: The index of the plane (should not be more than the number of planes
* in the given format).
* Queries how many bytes a pixel of the given @format takes.
*
* Queries the number of bytes per pixel for a given format in the given plane.
*
* Returns: The number of bytes per pixel in the given format's given plane.
* Return value: The number of bytes taken for a pixel of the given
* @format.
*/
int
cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format,
int plane);
_cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format);
/*
* _cogl_pixel_format_has_aligned_components:
@@ -294,17 +284,6 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format);
#define COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT(format) \
(((format) & COGL_A_BIT) && (format) != COGL_PIXEL_FORMAT_A_8)
/**
* cogl_pixel_format_get_n_planes:
* @format: The format for which to get the number of planes
*
* Returns the number of planes the given CoglPixelFormat specifies.
*
* Returns: The no. of planes of @format (at most %COGL_PIXEL_FORMAT_MAX_PLANES)
*/
int
cogl_pixel_format_get_n_planes (CoglPixelFormat format);
/**
* cogl_pixel_format_to_string:
* @format: a #CoglPixelFormat

View File

@@ -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 <robert@linux.intel.com>
*/
#ifndef __COGL_QUATERNION_PRIVATE_H__
#define __COGL_QUATERNION_PRIVATE_H__
#include <glib.h>
/* 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__ */

671
cogl/cogl/cogl-quaternion.c Normal file
View File

@@ -0,0 +1,671 @@
/*
* 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 <robert@linux.intel.com>
*
* 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
*/
#include "cogl-config.h"
#include <cogl-util.h>
#include <cogl-quaternion.h>
#include <cogl-quaternion-private.h>
#include <cogl-matrix.h>
#include <cogl-vector.h>
#include <cogl-euler.h>
#include "cogl-gtype-private.h"
#include <string.h>
#include <math.h>
#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;
}
}
gboolean
cogl_quaternion_equal (const void *v1, const void *v2)
{
const CoglQuaternion *a = v1;
const CoglQuaternion *b = v2;
g_return_val_if_fail (v1 != NULL, FALSE);
g_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;
g_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;
g_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;
g_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;
}

560
cogl/cogl/cogl-quaternion.h Normal file
View File

@@ -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 <robert@linux.intel.com>
*/
#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION)
#error "Only <cogl/cogl.h> can be included directly."
#endif
#ifndef __COGL_QUATERNION_H__
#define __COGL_QUATERNION_H__
#include <cogl/cogl-types.h>
#include <cogl/cogl-vector.h>
G_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
* <ulink url="http://en.wikipedia.org/wiki/Gimbal_lock">"Gimbal lock"</ulink>
* where two of the axis of rotation may become aligned and you loose a
* degree of freedom.
* .
*/
#include <cogl/cogl-vector.h>
#include <cogl/cogl-euler.h>
#include <glib-object.h>
/**
* 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 <literal>[w (x, y, z)]</literal>.
*
* 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:
*
* <itemizedlist>
* <listitem>
* <ulink url="http://mathworld.wolfram.com/Quaternion.html"/>
* </listitem>
* <listitem>
* <ulink url="http://www.gamedev.net/reference/articles/article1095.asp"/>
* </listitem>
* <listitem>
* <ulink url="http://www.cprogramming.com/tutorial/3d/quaternions.html"/>
* </listitem>
* <listitem>
* <ulink url="http://www.isner.com/tutorials/quatSpells/quaternion_spells_12.htm"/>
* </listitem>
* <listitem>
* 3D Maths Primer for Graphics and Game Development ISBN-10: 1556229119
* </listitem>
* <listitem>
* <ulink url="http://www.cs.caltech.edu/courses/cs171/quatut.pdf"/>
* </listitem>
* <listitem>
* <ulink url="http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56"/>
* </listitem>
* </itemizedlist>
*
*/
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
*/
gboolean
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.
*
* <note>It is possible to multiply the @a quaternion in-place, so
* @result can be equal to @a but can't be equal to @b.</note>
*
* 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:
* <itemizedlist>
* <listitem>
* commutative: No
* </listitem>
* <listitem>
* constant velocity: Yes
* </listitem>
* <listitem>
* torque minimal (travels along the surface of the 4-sphere): Yes
* </listitem>
* <listitem>
* more expensive than cogl_quaternion_nlerp()
* </listitem>
* </itemizedlist>
*/
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:
* <itemizedlist>
* <listitem>
* commutative: Yes
* </listitem>
* <listitem>
* constant velocity: No
* </listitem>
* <listitem>
* torque minimal (travels along the surface of the 4-sphere): Yes
* </listitem>
* <listitem>
* faster than cogl_quaternion_slerp()
* </listitem>
* </itemizedlist>
*/
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);
G_END_DECLS
#endif /* __COGL_QUATERNION_H__ */

View File

@@ -155,9 +155,6 @@ _cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds,
CoglSpan *last_y_span;
uint8_t *waste_buf = NULL;
g_return_val_if_fail (format != COGL_PIXEL_FORMAT_ANY, NULL);
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, 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,
@@ -166,7 +163,7 @@ _cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds,
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, 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
@@ -212,23 +209,17 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds,
{
int bmp_rowstride = cogl_bitmap_get_rowstride (source_bmp);
CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
int bpp;
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;
/* We only support single plane formats here */
if (cogl_pixel_format_get_n_planes (source_format) == 1)
return FALSE;
bmp_data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0, error);
if (bmp_data == NULL)
return FALSE;
bpp = cogl_pixel_format_get_bytes_per_pixel (source_format, 0);
if (need_x)
{
src = (bmp_data + ((src_y + (int) y_iter->intersect_start - dst_y) *
@@ -977,12 +968,11 @@ cogl_texture_2d_sliced_new_from_data (CoglContext *ctx,
CoglTexture2DSliced *tex_2ds;
g_return_val_if_fail (format != COGL_PIXEL_FORMAT_ANY, NULL);
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, NULL);
g_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, 0);
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format);
/* Wrap the data into a bitmap */
bmp = cogl_bitmap_new_for_data (ctx,

View File

@@ -204,12 +204,11 @@ cogl_texture_2d_new_from_data (CoglContext *ctx,
CoglTexture2D *tex_2d;
g_return_val_if_fail (format != COGL_PIXEL_FORMAT_ANY, NULL);
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, NULL);
g_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, 0);
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format);
/* Wrap the data into a bitmap */
bmp = cogl_bitmap_new_for_data (ctx,

Some files were not shown because too many files have changed in this diff Show More