Compare commits

..

124 Commits

Author SHA1 Message Date
Carlos Garnacho
c90f39ace5 clutter: Always snoop key events for a11y
In the case a11y is required, the screen reader is very much
interested in getting an uniterrupted flow of key events. It attempts
so by setting a ::captured-event callback on the ClutterStage, but
that falls short with our MetaDisplay event handler, as clutter events
can be stopped before a11y gets a chance to see them.

This kind of selective amnesia wrt key events is not new, in X11 those
go unheard of by the WM as long as a client is focused and no grabs hold,
so it is clients' responsibility to talk with AT bridge.

This commit doesn't yet change that for X11, but we can do this right
away from the compositor on Wayland, and without any chance to be
tampered by clients.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1328
2020-06-23 18:14:22 +02:00
Michel Dänzer
2e5b767c01 gpu/kms: Turn off CRTCs as well for DPMS
This avoids some issues which could happen on some setups[0] due to
meta-native-renderer.c:dummy_power_save_page_flip →
meta_onscreen_native_swap_drm_fb implicitly turning of the primary
plane (by destroying the KMS framebuffer assigned to it):

* drmModeObjectSetProperty could return an "Invalid argument" error
  between setting a non-empty cursor with drmModeSetCursor(2) and
  enabling the primary plane again:

  Failed to DPMS: Failed to set connector 69 property 2: Invalid argument

  (This was harmless other than the error message, as we always re-set
  a mode on the CRTC after setting the DPMS property to on, which
  enables the primary plane and implicitly sets the DRM property to on)

* drmModeSetCursor(2) could return an "Invalid argument" error between
  setting the DPMS property to on and enabling the primary plane again:

  Failed to set hardware cursor (drmModeSetCursor failed: Invalid argument), using OpenGL from now on

[0] E.g. with the amdgpu DC display code.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1240
2020-06-23 12:04:14 +02:00
Daniel van Vugt
f511f94aa2 clutter-stage-cogl: Fix uninitialized variable use_clipped_redraw
I noticed my system would fall back to the slow unclipped (and
uncullable) paint path whenever a window touched the left edge of
the screen. Turns out that was a red herring. Just that
`use_clipped_redraw` was uninitialized so clipping/culling was used
randomly.

So the compiler failed to notice `use_clipped_redraw` was uninitialized.
Weirdly, as soon as you fix that it starts complaining that `buffer_age`
might be uninitialized, which appears to be wrong. So we initialize that
too, to shut up the compiler warnings/errors.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1323
2020-06-23 09:11:54 +00:00
Robert Mader
3187fe8ebc shaped-texture: Reintroduce clip_region
In commit 4c1fde9d MetaCullable related code was moved out of
MetaShapedTexture into MetaSurfaceActor. While generally desirable,
this removed drawing optimizations in MetaShapedTexture for partial
redraws. The common case for fully obscured actors was still supposed
to work, but it was now discovered that it actually did not.

This commit revert parts of 4c1fde9d: it reintroduces clipping
to MetaShapedTexture but leaves all culling and actor related logic
in MetaSurfaceActor.

Thanks to Daniel van Vugt for uncovering the issue.

Fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/850
Fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/1295

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1326
2020-06-22 17:56:01 +02:00
Sebastian Keller
f5c8e0d96d window/x11: Don't stop early when trying to find default focus window
When trying to find a default focus window, the code iterates through a
queue of candidates with a timeout between each candidate. If the window
the current timeout is waiting for gets destroyed, this process just
stops instead of trying the next window in the queue.

This issue was made more likely to be triggered with the previous change
to the closed-transient-no-input-parents-queued-default-focus-destroyed
test due to the introduction of a wait, which can introduce a
delay between the two destroy commands.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1325
2020-06-22 17:12:49 +02:00
Sebastian Keller
c3d1320343 tests/stacking: Avoid random failures in focus tests
Some tests were not waiting for the test client to actually issue
destroy commands before checking their effect on the window focus.

Similarly when mutter is supposed to change the focus based on a delay
by sending a WM_TAKE_FOCUS to the client, this also could fail without
synchronization with the client before checking the result.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1325
2020-06-21 05:00:03 +02:00
Jonas Dreßler
5c5dcd58b5 bind-constraint: Don't update preferred size if source contains actor
The ClutterBindConstraint will change the preferred size an actor
reports so it returns the same size as the source actor in some cases.
This behavior was introduced recently with 4f8e518d.

This can lead to infinite loops in case the source actor is a parent of
the actor the BindConstraint is attached to, that's because calling
get_preferred_size() on the source will recursively call
get_preferred_size() on the actor again.

So to avoid those loops, check if the source is a parent of the actor
we're attached to and don't update the preferred size in that case.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1282
2020-06-19 14:59:27 +00:00
Jonas Dreßler
6ea0f8facc clutter/clone: Build scale factor for transformation during allocation
For ClutterClones we need to apply a scale to the texture of the clone
to ensure the painted texture of the source actor actually fits the
allocation of the clone. We're doing this using the transformation
matrix instead of using the scale_x/scale_y properties of ClutterActor
to allow users to scale ClutterClones using that API independently.

Now it's quite a bad idea to get the allocation boxes for calculating
that scale using clutter_actor_get_allocation_box(), since that method
will internally do an immediate relayout of the stage in case the actor
isn't allocated. Another side effect of that approach is that it makes
it impossible to invalidate the transform (which will be needed when we
start caching those matrices) properly.

So since we eventually allocate both the source actor and the clone
ourselves anyway, we can simply use the allocation box inside
clutter_clone_allocate() (which is definitely updated and valid at that
point) to calculate the scale factor.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1181
2020-06-18 20:19:07 +00:00
Jonas Dreßler
0c1e5b4ee5 clutter/clone: Use scale factor of 1.0 for Z axis
It seems wrong to use the scale factor of the X axis on the Z axis and
it looks like this has been accidentally changed in commit 570fa3f044.

So use a factor of 1.0 instead to not scale the Z axis at all because
the layout machinery only works in X and Y coordinates.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1181
2020-06-18 20:19:07 +00:00
Jonas Dreßler
ad50d2cfc4 clutter/actor: Always query layout manager when getting size
There are cases where a layout manager used by an actor also wants to
return a custom size when the actor has no children, for example in case
the layout manager requests a fixed size. This is currently impossible
because we only query the layout manager when calculating the preferred
size if the actor has children.

So fix that and also use the layout managers size negotiation functions
in case the actor has no children.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1322
2020-06-18 21:16:17 +02:00
Adam Jackson
1398c6dfa4 cogl: Remove some unused #define GL_BLAH safeties
None of these constants are referenced in the files defining them.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
ab9f241cc5 cogl: Remove some dead stores not flagged by the compiler
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
1f5d6a01f5 cogl: Remove unused driver includes
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
ca79073014 cogl: Move graphics reset status into the driver vtable
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
0b6f5c6f55 cogl: Move GL-specific uniform code to the driver vtable
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
e2c2a332e6 cogl: Add and use sampler init/free hooks in the CoglDriverVtable
next_fake_sampler_object_number moves to CoglGLContext.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
245977e525 cogl: Move texture unit state to CoglGLContext
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
e03c75bac7 cogl: Add a slot for driver-private state to CoglContext
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
4ff58cc63f cogl: Move some pre-layer-change-notify code into the driver
A CoglTextureUnit is a GL-specific type, this should happen in the
driver not the core.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
462df7e61a cogl: Move some GL-specific GLSL details into the driver
_cogl_shader_set_source_with_boilerplate and _cogl_shader_compile_real
have enough GL assumptions that it makes sense to push them into the
backend. Taken together their only callers are under driver/gl, so.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
1285619bcf cogl: Move GL context/version details into the driver
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
d6f5ac5603 cogl: Remove now-unused CoglGpuInfo
This had been an entirely-too-GL-aware collection of renderer queries,
mostly to work around driver bugs and handle software drivers
intelligently. The driver workarounds have been removed (fix your
driver, and if you can't because it's closed-source, fix that first),
and we now delegate the am-i-software-or-not logic to the backend, so
this can all go

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:55 -04:00
Adam Jackson
d133f94f8f cogl: Introduce and use cogl_context_is_hardware_accelerated
We delegate the answer through CoglDriverVtable::is_hardware_accelerated
since this is properly a property of the renderer, and not something the
cogl core should know about. The answer given for the nop driver is
admittedly arbitrary, yes it's infinitely fast but no there's not any
"hardware" making it so.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1194
2020-06-18 13:55:14 -04:00
Sebastian Keller
e216d9c6ad clutter/stage: Make paint_to_buffer use the correct texture/buffer size
The size of the buffer the texture will be written to by
paint_to_buffer() is determined based on
meta_screen_cast_area_stream_src_get_specs() which uses roundf() to
calculate the width and height after scaling. Because the size of the
texture to be written to that buffer is calculated using ceilf(), it
might exceed the allocated buffer when using fractional scaling.

In 3.36 paint_to_buffer() is used from capture_view() which also uses
roundf() to allocate its buffer. Here this leads to a memory corruption
resulting in a crash when taking screenshots of an area.

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

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1320
2020-06-17 16:14:57 +00:00
Carlos Garnacho
79050004b0 wayland: Avoid popup grab focus changes if there's an implicit grab
Event delivery with grabbing popups stay essentially the same within
the grabbing client, we still must honor the implicit grab as long as
there is one.

This is however not the case, the popup_grab_focus() function ignores
the button state. The popup_grab_button() function will already indirectly
re-sync the focus surface after the last button is released, so checking
for button state in popup_grab_focus() is sufficient to make the implicit
grab honored with popup grabs involved.

Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1275

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1270
2020-06-17 13:47:38 +00:00
Jonas Ådahl
e5ea8f5483 stage/x11: Check that message is WM_PROTOCOLS before assuming so
When a touch sequence was rejected, we'd update the event timestamps of
incoming touch events to help with implementing grabs. This was done by
sending a ClientMessage with a counter, and comparing the counter to
decide whether we're seing a replayed event or not.

This had the unforseen consequence that we would potentially end up
destroying all actors including the stage, since, when mutter receives a
ClientMessage event, it would assume that it's a WM_PROTOCOLS event, and
handle it as such. The problem with this approach is that it would
ignore fact that there might be other ClientMessage types sent to it,
for example the touch synchronization one. What could happen is that the
touch count value would match up with the value of the WM_DELETE_WINDOW
atom, clutter would treat this as WM_PROTOCOLS:WM_DELETE_WINDOW, which
it'd translate to clutter_actor_destroy(stage).

Destroying the stage in such a way is not expected, and caused wierd
crashes in different places depending on what was going on.

This commit make sure we only treat WM_PROTOCOLS client messages as
WM_PROTOCOLS client messages effectively avoiding the issue.

This fixes crashes such as:

 #0  meta_window_get_buffer_rect (window=0x0, rect=rect@entry=0x7ffd7fc62e40) at core/window.c:4396
 #1  0x00007f1e2634837f in get_top_visible_window_actor (compositor=0x297d700, compositor=0x297d700) at compositor/compositor.c:1059
 #2  meta_compositor_sync_stack (compositor=0x297d700, stack=<optimized out>, stack@entry=0x26e3140) at compositor/compositor.c:1176
 #3  0x00007f1e263757ac in meta_stack_tracker_sync_stack (tracker=0x297dbc0) at core/stack-tracker.c:871
 #4  0x00007f1e26375899 in stack_tracker_sync_stack_later (data=<optimized out>) at core/stack-tracker.c:881
 #5  0x00007f1e26376914 in run_repaint_laters (laters_list=0x7f1e2663b7d8 <laters+24>) at core/util.c:809
 #6  run_all_repaint_laters (data=<optimized out>) at core/util.c:826
 #7  0x00007f1e26b18325 in _clutter_run_repaint_functions (flags=flags@entry=CLUTTER_REPAINT_FLAGS_PRE_PAINT) at clutter-main.c:3448
 #8  0x00007f1e26b18fc5 in master_clock_update_stages (master_clock=0x32d6a80, stages=0x4e5a740) at clutter-master-clock-default.c:437
 #9  clutter_clock_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at clutter-master-clock-default.c:567
 #10 0x00007f1e27e48049 in g_main_dispatch (context=0x225b8d0) at gmain.c:3175
 #11 g_main_context_dispatch (context=context@entry=0x225b8d0) at gmain.c:3828
 #12 0x00007f1e27e483a8 in g_main_context_iterate (context=0x225b8d0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3901
 #13 0x00007f1e27e4867a in g_main_loop_run (loop=0x24e29f0) at gmain.c:4097
 #14 0x00007f1e2636a3dc in meta_run () at core/main.c:666
 #15 0x000000000040219c in main (argc=1, argv=0x7ffd7fc63238) at ../src/main.c:534

and

 #0  0x00007f93943c1f25 in raise () at /usr/lib/libc.so.6
 #1  0x00007f93943ab897 in abort () at /usr/lib/libc.so.6
 #2  0x00007f9393e1e062 in g_assertion_message (domain=<optimized out>, file=<optimized out>, line=<optimized out>, func=0x7f93933e6860 <__func__.116322> "meta_x11_get_stage_window",
 #3  0x00007f9393e4ab1d in g_assertion_message_expr ()
 #4  0x00007f939338ecd7 in meta_x11_get_stage_window (stage=<optimized out>) at ../mutter/src/backends/x11/meta-stage-x11.c:923
 #5  0x00007f939339e599 in meta_backend_x11_cm_translate_device_event (x11=<optimized out>, device_event=0x55bc8bcfd6b0) at ../mutter/src/backends/x11/cm/meta-backend-x11-cm.c:381
 #6  0x00007f939339f2e2 in meta_backend_x11_translate_device_event (device_event=0x55bc8bcfd6b0, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:179
 #7  0x00007f939339f2e2 in translate_device_event (device_event=0x55bc8bcfd6b0, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:208
 #8  0x00007f939339f2e2 in maybe_spoof_event_as_stage_event (input_event=0x55bc8bcfd6b0, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:284
 #9  0x00007f939339f2e2 in handle_input_event (event=0x7fff62d60490, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:309
 #10 0x00007f939339f2e2 in handle_host_xevent (event=0x7fff62d60490, backend=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:413
 #11 0x00007f939339f2e2 in x_event_source_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at ../mutter/src/backends/x11/meta-backend-x11.c:467
 #12 0x00007f9393e6c39e in g_main_dispatch (context=0x55bc89dd03e0) at ../glib/glib/gmain.c:3179
 #13 0x00007f9393e6c39e in g_main_context_dispatch (context=context@entry=0x55bc89dd03e0) at ../glib/glib/gmain.c:3844
 #14 0x00007f9393e6e1b1 in g_main_context_iterate (context=0x55bc89dd03e0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:3917
 #15 0x00007f9393e6f0c3 in g_main_loop_run (loop=0x55bc8a042640) at ../glib/glib/gmain.c:4111
 #16 0x00007f9393369a0c in meta_run () at ../mutter/src/core/main.c:676
 #17 0x000055bc880f2426 in main (argc=<optimized out>, argv=<optimized out>) at ../gnome-shell/src/main.c:552

Related: https://gitlab.gnome.org/GNOME/mutter/-/issues/338
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/951

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1317
2020-06-16 13:59:15 +00:00
Jonas Dreßler
0ab1a9fa44 clutter/actor: Clean up clutter_actor_event()
We can easily do without the goto statement and use only one switch
statement in this function, so tidy it up a bit.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1275
2020-06-16 10:09:27 +00:00
Jonas Dreßler
cb0cc42651 clutter: Also remove event sequences on TOUCH_CANCEL events
We don't want to leave event sequences around when touches are
cancelled, so also remove those from the ClutterInputDevice's hashtable.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1275
2020-06-16 10:09:26 +00:00
Jonas Dreßler
b36cfb5bdc clutter/stage: Don't update modifier state when queuing event
The modifier state of the input device is supposed to be set to the
newest state, while the modifier state detail of the event is set to the
last state before the event (so not including the changes triggered by
the event).

So since the modifier state of the event is the last state anyway, the
state of the ClutterInputDevice is supposed to be set by the backend and
not by the stage while queuing the event, so stop setting the state
here.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1275
2020-06-16 10:09:26 +00:00
Jonas Dreßler
7539de2320 clutter/input-device: Make clutter_input_device_get_actor() public
Make the clutter_input_device_get_actor() API public and remove
clutter_input_device_get_pointer_actor() in favour of the new function.

This allows also getting the "pointer" actor for a given touch sequence,
not only for real pointer input devices like mice.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1275
2020-06-16 10:09:26 +00:00
Jonas Dreßler
8de91f1053 clutter/stage: Switch to clutter_seat_peek_devices()
Switch from clutter_seat_list_devices() to the new peek_devices() method
of ClutterSeat in cases where we're only looping through the returned
list without manipulating it. This way we don't have to unnecessarily
copy around the list of devices.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1275
2020-06-16 10:09:26 +00:00
Jonas Dreßler
45c14f74b4 clutter/seat: Add private method to peek list of input devices
Add a method to ClutterSeat that allows peeking the list of input
devices and allow looping through devices a bit faster. The API left is
private so we can make use of peeking the GList internally, but don't
have to expose any details to the outside, which means we'd have to
eventually stick with a GList forever to avoid breaking API.

Since we now have the peek_devices() API internally, we can implement
ClutterSeats public list_devices() API using g_list_copy() on the list
returned by peek_devices().

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1275
2020-06-16 10:09:26 +00:00
Jonas Dreßler
d4457d1f7f clutter/seat: Fix a typo in an introspection doc
Make sure that function is actually skipped, gobject-introspection
should probably complain about that function which can't be found.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1275
2020-06-16 10:09:26 +00:00
Jonas Dreßler
0ba15df57c clutter/stage: Don't do newly queued relayouts after allocation cycle
While it's strongly discouraged, it is possible to queue a new relayout
of an actor in the middle of an allocation cycle, we warn about it but
don't forbid it.

With the introduction of the "shallow relayout" API, our handling of
those relayouts silently changed: Before introducing "shallow
relayouts", we'd handle them on the next stage update, but with the
priv->pending_relayouts hashtable and the
priv->pending_relayouts_version counter, we now do them immediately
during the same allocation cycle (the counter is increased by 1 when
queuing the relayout and we switch to a new GHashTableIter after
finishing the current relayout, which means we'll now do the newly
queued relayout).

This change in behavior was probably not intended and wasn't mentioned
in the commit message of 5257c6ecc2, so
switch back to the old behavior, which is more robust in preventing
allocation-loops. To do this, use a GSList instead of GHashTable for the
pending_relayouts list, and simply steal that list before doing the
relayouts in _clutter_stage_maybe_relayout().

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1267
2020-06-16 09:39:43 +00:00
Corentin Noël
e09ac67698 window-actor-x11: switch the signal callback argument and data on shadow factory change
invalidate_shadow takes the MetaWindowActorX11 as argument and not the MetaShadowFactory.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1314
2020-06-15 13:22:08 +00:00
Jonas Dreßler
e6a93326bf window-actor: Don't freeze actor updates during the size-change effect
As explained in the last commits, we'll let gnome-shell take care of
this since freezing and thawing needs to be decoupled from the effect
starting and ending.

So stop freezing the MetaWindowActor when starting the effect and
thawing the actor when ending the effect.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1250
2020-06-15 13:10:16 +00:00
Jonas Dreßler
fb474fb612 window-actor: Make freezing and thawing of actor updates public API
As explained in the last commit, gnome-shell needs to be able to thaw
window actor updates during its size-change effect is active.

So make meta_window_actor_freeze() and meta_window_actor_thaw() public
API, which will allow the shell to freeze and thaw actor updates itself.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1250
2020-06-15 13:10:16 +00:00
Jonas Dreßler
d12dc993d1 window-actor: Allow syncing actor geometry while effect is running
The size-change animation in gnome-shell needs to sync the window actors
geometry during the animation, it currently does this by notifying the
compositor that the animation was finished before it actually is.

This causes a few bugs in Mutter though, since it will now emit the
"effects-completed" signal on the window actor even though they aren't
completed.

To fix that, we need to decouple freezing and thawing of actor updates
from window effects and allow gnome-shell to thaw actor updates before
it notifies Mutter that the effect is completed.

The first step for this is allowing to sync the actor geometry while an
effect is active, this should be redundant since effects which actually
need to inhibit those updates will freeze the actor anyway. Also a
geometry change happening while another effect is active will kill the
old effect anyway because MetaPluginManager kills all the active window
effects before starting a new one; so the new size-change effect for any
geometry change is going to kill the current effect.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1250
2020-06-15 13:10:16 +00:00
Corentin Noël
6414b8c45f clutter/stage: Set the right type for the paint-view argument
As it is a cairo_region_t, we can proide the right GType value for it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1313
2020-06-11 23:01:39 +02:00
Jonas Ådahl
19b467aa01 crtc-kms: Include MetaCrtc in MetaCrtcKms struct
Otherwise it can't be a GObject inheriting MetaCrtc. This fixes warning
logged as

"invalid uninstantiatable type '(null)' in cast to 'MetaCrtcKms'"

Fixes: 1ce9e379d9

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1308
2020-06-11 11:52:53 +02:00
Jonas Ådahl
e089e53b24 crtc-kms: Make KMS CRTC mode a type inheriting MetaCrtcMode
It carries the drmModeModeInfo copy in it's instance struct, instead of
the `driver_private` it was using before.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287

This version of the commit includes fixes from:

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1305
2020-06-11 09:20:16 +00:00
Daniel van Vugt
bad1a7fd0c backends-x11: Remove g_new0 overwriting g_object_new
The object starts out right, and then gets overwritten with zeroes:

```
  crtc_xrandr = g_object_new (META_TYPE_CRTC_XRANDR,
                              "id", crtc_id,
                              "gpu", gpu,
                              "all-transforms", all_transforms,
                              NULL);

  crtc_xrandr = g_new0 (MetaCrtcXrandr, 1);
```

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1296

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1306
2020-06-11 07:53:02 +00:00
Sebastian Keller
51a8193c16 wayland/keyboard: Fix anonymous file leak on repeated keymap changes
keymap_rofile was being overwritten without the old one being free'd on
repeated calls of meta_wayland_keyboard_take_keymap().

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1304
2020-06-11 07:23:18 +00:00
Sebastian Keller
94fb82137f backends/native: Fix input device touch hash table leak
It was emptied but never unref'ed in finalize.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1304
2020-06-11 07:23:18 +00:00
Georges Basile Stavracas Neto
49408e8f9f Revert "crtc-kms: Make KMS CRTC mode a type inheriting MetaCrtcMode"
This reverts commit 09078762a, which breaks Mutter.
2020-06-10 23:11:21 -03:00
Jonas Dreßler
77d359cdc3 clutter/align-constraint: Don't take source actors position into account
ClutterAlignConstraint currently assumes the source actor is positioned
in the same coordinate system as the actor it's attached to and
automatically offsets the adjusted allocation by the origin of the
source actor.

This behavior is only valid though in case the source actor is a sibling
of the constraint actor. If the source actor is somewhere else in the
actor tree, the behavior gets annoying because the constraint actor is
offset by (seemingly) random positions.

To fix this, stop offsetting the constraint actors allocation by the
position of the source.

To still make it possible to align the constraint actors origin with the
origin of the source, no longer override the origin of the allocation
in the AlignConstraint. This allows users to align the origin using a
BindConstraint, binding the actor position to the position of the
source, which is more flexible and also more elegant.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/737
2020-06-10 19:20:32 +00:00
Jonas Dreßler
590b9b8c86 clutter/align-constraint: Add pivot-point property
Add a new pivot-point property to the ClutterAlignConstraint, similar to
the pivot point used by ClutterActor, defining the point in the
constraint actor around which the aligning is applied to the actor.

Just as the ClutterActor property, this property is defined using a
GraphenePoint.

By default this property remains set to (-1, -1) and the actor
will always be aligned inside the source actor, preserving the existing
behavior of ClutterAlignConstraint.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/737
2020-06-10 19:20:32 +00:00
Jonas Ådahl
09078762ac crtc-kms: Make KMS CRTC mode a type inheriting MetaCrtcMode
It carries the drmModeModeInfo copy in it's instance struct, instead of
the `driver_private` it was using before.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:51 +00:00
Jonas Ådahl
352c2ec7b8 output-kms: Remove old FIXME
Trying to figure out what this comment was actually about, it turns out
that MSC means Media Stream Counter, and as mentioned in an article[0]
is related to DRI3 and the X11 Present extension. Anyway, the comment
has been there raising questions for some years now, I think we can
remove it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:51 +00:00
Jonas Ådahl
4b37c2e446 crtc-mode: Move away fields from public MetaCrtcMode struct
The ID and name are just moved into the instance private, while the rest
is moved to a `MetaCrtcModeInfo` struct which is used during
construction and retrieved via a getter. Opens up the possibility to
add actual sub types.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:51 +00:00
Jonas Ådahl
980ece9a4b crtc: Move out MetaCrtcMode into its own file
It's somewhat annoying to have two very closely named types in the same
file. It's also about to grow some, so better move it to its own file.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:51 +00:00
Jonas Ådahl
1ce9e379d9 crtc: Make implementations inherit MetaCrtc
Just as with MetaOutput, instead of the home baked "inheritance" system,
using a gpointer and a GDestroyNotify function to keep the what
effectively is sub type details, make MetaCrtc an abstract derivable
type, and make the implementations inherit it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:51 +00:00
Jonas Ådahl
4a4f2d8264 output: Make implementations inherit MetaOutput
Instead of the home baked "inheritance" system, using a gpointer and a
GDestroyNotify function to keep the what effectively is sub type
details, make MetaOutput an abstract derivable type, and make the
implementations inherit it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:51 +00:00
Jonas Ådahl
4920b5064d tests/monitor-unit-tests: Only set suggested_x/y when relevant
It's used for two things: avoid reading configs, and actual hotplug
update mode. The former requires the suggested position to be (-1, -1)
to trick the monitor configuration generator to skip using the suggested
position even if hotplug update mode is set to TRUE. The latter should
use the actual hotplug mode coordinates.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:51 +00:00
Jonas Ådahl
26ddb07066 monitor-manager-dummy: Remove redundant suggested_x/y setting
The `hotplug_update_mode` is set to FALSE, so they should never be
queried.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
574b49ed95 monitor: Check hotplug update mode before getting suggested x/y
Without it being TRUE, the suggested x/y has no meaning.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
6697b0d069 output/xrandr: Fix include guards
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
092c5304a9 crtc: Move MetaCrtcConfig field to instance private
Last piece before MetCrtc can be made a derivable type.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
c3fc6025b1 crtc: Move all_transforms field into instance private
Now set as a property during construction. Only actually set by the
Xrandr backend, as it's the only one currently not supporting all
transforms, which is the default.

While at it, move the 'ALL_TRANFORMS' macro to meta-monitor-tranforms.h.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
1406348be4 output: Move output info to MetaOutputInfo struct
The output info is established during construction and will stay the
same for the lifetime of the MetaOutput object. Moving it out of the
main struct enables us to eventually clean up the MetaOutput type
inheritence to use proper GObject types.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
46e3d20057 tests/monitor-unit-tests: Make hotplug mode part of test setup
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
9bcf1d0238 monitor-manager: Remove useless comment
An old forgotten FIXME. If we actually need better hueristics, we should
probably know why we need that, and open a bug about it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
b69111d8e6 monitor-manager: Rename *Info structs to *Assignment
MetaCrtcInfo and MetaOutputInfo did not represent information about
MetaCrtc and MetaOutput, but the result of the monitor configuration
assignment algorithm, thus rename it to MetaCrtcAssignment and
MetaOutputAssignment.

The purpose for this is to be able to introduce a struct that actually
carries information about the CRTCs and outputs, as retrieved from the
backend implementations.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
f71316c850 output: Move configureable state to instance private
That is is_presentation, is_primary, is_underscanning and backlight.

The first three are set during CRTC assignment as they are only valid
when active. The other is set separately, as it is untied to
monitor configuration.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
9186b6d6b0 monitor-manager: Remove is_dirty from MetaCrtc and MetaOutput
It was used during configuration to ensure that we always dealt with
every output and CRTC. Do this without polluting the MetaOutput and
MetaCrtc structs with intermediate variables not used by the
corresponding types themself.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
55719afcbf output: De-glib:ify some struct field types
Just use int instead of gint.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
e063947a16 output: Move winsys_id into instance private and rename to id
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
a42eed0231 crtc: Move CRTC id field into instance private
Set during construction, retrieved using helper.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
f4fd92d8e8 output: Move MetaGpu field to instance private
Set during construction only, retrieved using helper.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
2ebd43cba9 crtc: Move MetaGpu field to instance-private
Users either set during construction, or get via the helper.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
2724f36527 tests/monitor-unit-tests: Set initial state during backend construction
This way we can construct CRTCs and Outputs and associated them with the
fake GPUs at construction.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:50 +00:00
Jonas Ådahl
569a183828 crtc: Move renderer private to MetaKmsCrtc
It's used only by the native cursor renderer.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
2020-06-10 18:54:49 +00:00
Jonas Dreßler
620dcf3364 clutter/actor: Properly detect uninitialized allocations when easing
Now that we have a proper way to mark our allocation as uninitialized,
make use of that and only disallow implicit transitions of the
"allocation" property if that is the case.

This fixes a bug where easing the allocation of an actor is impossible
when someone queued a relayout on it (or a child of it) before.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1290
2020-06-10 14:23:54 +02:00
Jonas Dreßler
eb9cd3857d clutter/actor: Set initial allocation to uninitialized ClutterActorBox
We currently initialize the ClutterActorBox of the actors allocation to
zero, but there's a difference between a valid zero-allocation and an
actor having never been allocated. Currently it's impossible for us to
detect the latter case in a reliable way and we use the needs_allocation
flag for this, which may also be set in other situations.

So initialize the allocation of actors to the newly added UNINITIALIZED
ClutterActorBox, which will make it easier to detect whether an actor
already got its initial allocation.

This also fixes another issue right now: Actors which get allocated a
(valid) zero allocation, will now notify the "allocation" property in
this case.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1290
2020-06-10 14:23:54 +02:00
Jonas Dreßler
0bfb995bff clutter/actor-box: Allow marking boxes as uninitialized
Add support for an artificial UNINITIALIZED marking for ClutterActorBox,
done by setting the boxes origin to Infinity and its size to -Infinity.
That is a value that's considered an invalid allocation by Clutter and
which can never be set by sane code.

This will allow setting the allocation of ClutterActors to an
UNINITIALIZED box when creating actors or when removing them from the
scenegraph and makes it possible to explicitely detect uninitialized
allocations, which is useful in a few cases.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1290
2020-06-10 14:22:47 +02:00
Jonas Ådahl
932340a989 background-content: Shut up warning
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1303
2020-06-10 10:42:18 +02:00
Georges Basile Stavracas Neto
ca0156e9a7 background-content: Render background slices relative to actor box
The current code assumes that the actor will always have the same
size and position of the background texture, but part of the implicit
contract of being a ClutterContent is being able to render itself
at any given actor, at any given size.

For example, if the current code is given an actor with 0x0+100+100
as geometry, and no clipped region, it'll render not the whole
background, but the 0x0+100+100 rectangle of the background. In
practice, the actor geometry acts like a "clip mask" over the
background texture, due to the assumption that the actor will
always have the same size of the monitor.

Make the calculation of the texture slices relative to the actor
box.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1302
2020-06-09 17:07:02 -03:00
Georges Basile Stavracas Neto
6d75b4fc53 background-content: Simplify method call
It's always passing the same pipeline and texture rect, simplify
by passing the MetaBackgroundContent instance itself.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1302
2020-06-09 17:07:02 -03:00
Georges Basile Stavracas Neto
6bd382ad23 background-actor: Use MetaBackgroundContent
MetaBackgroundActor is still necessary for culling purposes,
but now the actual rendering of the background is delegated
to MetaBackgroundContent, as well as the sizing information.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1302
2020-06-09 17:07:02 -03:00
Georges Basile Stavracas Neto
a1b3d1a2a7 Introduce MetaBackgroundContent
MetaBackgroundContent is a ClutterContent implementation
that can render a background to any attached actor. Right
now, it preserves all the properties and the rendering
model of MetaBackgroundActor.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1302
2020-06-09 17:07:02 -03:00
Jonas Ådahl
53f61f3778 stack-tracker: Don't log warnings on race conditions
X11 window stacking operations are by nature prone to race conditions.
For example, we might queue a "raise above" operation, but before it
actually takes place, the sibling the window was to be rased above, is
withdrawn.

In these cases we'd log warnings even though they are expected to
happen. Downgrade these warnings to debug messages, only printed when
MUTTER_VERBOSE is set.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1300
2020-06-09 18:46:38 +00:00
Jonas Ådahl
74c0d9140c stack-tracker: Fix coding style of meta_stack_op_apply()
Change tabs to spaces, clean up variable declarations.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1300
2020-06-09 18:46:38 +00:00
Georges Basile Stavracas Neto
268336c21a clutter/actor: Allow animating content properties
ClutterActor allows animating effects, constraints, actions,
and the layout manager for property transitions. Extend this
functionality to the content as well.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1301
2020-06-09 15:09:26 -03:00
Jonas Dreßler
49e983b06e tests: Add a test for ClutterActors stage_views() API
Test that the stage-views list of ClutterActor is correct when moving an
actor, reparenting it, or hiding an actor up the hierarchy. Also test
that the "stage-views-changed" signal works as expected.

Don't test actor transforms for now because those aren't supported yet.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1196
2020-06-09 16:07:46 +00:00
Jonas Dreßler
0f97196d84 clutter/actor: Don't traverse whole actor tree for updating stage-views
We currently go through the whole tree of mapped actors on every paint
cycle to update the stage views actors are on. Even if no actors need
updating of their stage views, traversing the actor tree is still quite
expensive and shows up when using a profiler.

So tone down the amounts of full-tree traversals we have to do on every
paint cycle and only traverse a subtree if it includes an actor which
actually needs updating of its stage views.

We do that by setting the `needs_update_stage_views` flag to TRUE
recursively for all parents up to the stage when the stage-views list of
an actor gets invalidated. This way we end up updating a few more actors
than necessary, but can avoid searching the whole actor tree for actors
which have `needs_update_stage_views` set to TRUE.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1196
2020-06-09 16:07:46 +00:00
Jonas Dreßler
18c792d6f8 clutter/actor: Emit a signal when the stage-views an actor is on change
Add a new signal that's emitted when the stage views an actor being
painted on have changed, "stage-views-changed". For example this signal
can be helpful when tracking whether an actor is painted on multiple
stage views or only one.

Since we must clear the stage-views list when an actor leaves the stage
(actors that aren't attached to a stage don't get notified about the
stage views being changed/replaced), we also emit the new signal when an
actor gets detached from the stage (otherwise there would be an edge
case where no signal is emitted but it really should: An actor is
visible on a stage view, then detached from the stage, and then attached
again and immeditely moved outside the view).

Also skip the comparison of the old stage-views list and the new one if
nobody is listening to the signal to save some resources.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1196
2020-06-09 16:07:46 +00:00
Jonas Dreßler
675a97d58e clutter/actor: Add API to get the stage-views an actor is painted on
There are certain rendering techniques and optimizations, for example
the unredirection of non-fullscreen windows, where information about the
output/stage-view an actor is on is needed to determine whether the
optimization can be enabled.

So add a new method to ClutterActor that allows listing the stage-views
the actor is being painted on: clutter_actor_peek_stage_views()

With the way Clutter works, the only point where we can reliably get
this information is during or right before the paint phase, when the
layout phase of the stage has been completed and no more changes to the
actors transformation matrices happen. So to get the stage views the
actor is on, introduce a new step that's done on every master clock tick
between layout and paint cycle: Traversing through the actor tree and
updating the stage-views the mapped actors are going to be painted on.

We're doing this in a separate step instead of inside
clutter_actor_paint() itself for a few reasons: It keeps the code
separate from the painting code, making profiling easier and issues
easier to track down (hopefully), it allows for a new
"stage-views-changed" signal that doesn't interfere with painting, and
finally, it will make it very easy to update the resource scales in the
same step in the future.

Currently, this list is only invalidated on allocation changes of
actors, but not on changes to the transformation matrices. That's
because there's no proper API to invalidate the transformation matrices
ClutterActor implementations can apply through the apply_transform()
vfunc.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1196
2020-06-09 16:07:46 +00:00
Jonas Dreßler
8127494e52 clutter/stage: Rename update_resource_scales to clear_stage_views
When the stage views the stage is shown on are changed, ClutterStage
currently provides a clutter_stage_update_resource_scales() method
that allows invalidating the resource scales of all actors. With the new
stage-views API that's going to be added to ClutterActor, we also need a
method to invalidate the stage-views lists of actors in case the stage
views are rebuilt and fortunately we can re-use the infrastructure for
invalidating resource scales for that.

So since resource scales depend on the stage views an actor is on,
rename clutter_stage_update_resource_scales() and related methods to
clutter_stage_clear_stage_views(), which also covers resource scales.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1196
2020-06-09 16:07:46 +00:00
Jonas Dreßler
670f4f22fe clutter/stage: Remove _clutter_stage_get_max_view_scale_factor_for_rect
Since we now have _clutter_stage_get_views_for_rect(), we can easily
replace _clutter_stage_get_max_view_scale_factor_for_rect() with it and
remove that private method.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1196
2020-06-09 16:07:46 +00:00
Jonas Dreßler
e27d2702a8 clutter/stage: Add private method to get the stage-views of a rectangle
We'll need this method for implementing a new stage-views-on API for
ClutterActor which lists the stage views an actor is on.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1196
2020-06-09 16:07:46 +00:00
Daniel van Vugt
dfe33897db meson_options: Use libGLESv2.so.2 for COGL_DRIVER=gles2, not libGLESv2.so
The former is present on any system that supports OpenGL|ES 2. The latter
is just provided in developer packages. Since we access the library via
`g_module_open` it's safe to just rely on `libGLESv2.so.2`.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1282

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1298
2020-06-09 18:32:01 +08:00
Jonas Dreßler
90c20b185b clutter/actor: Disconnect from "layout-changed" signal on destroy
While the layout manager of a ClutterActor does get properly unset when
destroying an actor, we currently forget to disconnect the
"layout-changed" signal from it.

So do that, and while at it, also switch to using the signal id for
disconnecting from the signal instead of
g_signal_handlers_disconnect_by_func(), which caused problems before
because it might traverse the signal handler list.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1281
2020-06-08 17:23:05 +00:00
Jonas Dreßler
4d7c8d68bc clutter/actor: Mark offscreen-redirect property as flag everywhere
We currently are confusing g_param_spec_enum and g_param_spec_flags for
the offscreen-redirect property of ClutterActor. Since it's actually a
flag, make it a flag everywhere.

Fun fact: This was already partly done with
d7814cf63e, but that commit missed the
setter.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1292
2020-06-08 15:25:11 +00:00
Jonas Dreßler
455de5d6d3 clutter/align-constraint: Listen to queue-relayout signal of source
Just like the ClutterBindConstraint, the ClutterAlignConstraint should
listen to "queue-relayout" of its source actor, not
"notify::allocation". That's because the latter will queue a relayout
during an allocation cycle and might cause relayout loops.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1296
2020-06-08 14:58:15 +00:00
Sebastian Keller
99c9f4c1fa wayland/data-device: Don't create and leak unused memory on dnd
"offer" is overwritten with the result of meta_wayland_data_offer_new a
few lines later.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1293
2020-06-08 12:11:11 +00:00
Sebastian Keller
dd32ff018a wayland: Free selection streams streams after transfer
They were only being closed but never freed.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1293
2020-06-08 12:11:11 +00:00
Sebastian Keller
019643bad0 core: Free clipboard selection source on shutdown
The clipboard manager is the only code to ever set the display selection
source, so it should also be responsible for unsetting it when the
clipboard manager gets shut down.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1293
2020-06-08 12:11:11 +00:00
Sebastian Keller
a031ac067e core: Fix memory selection source leak after clipboard owner disappears
When an app disappears after some data from it has been copied to the
clipboard, the owner of the clipboard selection becomes a new memory
selection source. The initial reference this new selection source is
never unref'ed, which leads to this being leaked on the next clipboard
selection owner change.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1293
2020-06-08 12:11:11 +00:00
Peter Hutterer
f712387325 compositor: use XDG_CONFIG_HOME as initial lookup path for xkb
Using XDG_CONFIG_HOME allows users to place their keyboard configuration into
their home directory and have them loaded automatically.
libxkbcommon now defaults to XDG_CONFIG_HOME/xkb/ first, see
https://github.com/xkbcommon/libxkbcommon/pull/117

However - libxkbcommon uses secure_getenv() to obtain XDG_CONFIG_HOME and thus
fails to load this for the mutter context which has cap_sys_nice.
We need to manually add that search path as lookup path.

As we can only append paths to libxkbcommon's context, we need to start with
an empty search path set, add our custom path, then append the default search
paths.

The net effect is nil where a user doesn't have XDG_CONFIG_HOME/xkb/.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/936
2020-06-08 11:29:30 +00:00
Jonas Ådahl
1eaf9e5f63 tests/clutter/timeline-interpolate: Maximize error tolerance
Simply to make it less flaky.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1291
2020-06-06 00:27:40 +02:00
Jonas Ådahl
7222bdde57 tests/clutter/timeline: Lower FPS even further
It's still flaky running in CI, lets run it even slower.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1291
2020-06-06 00:27:40 +02:00
Jonas Ådahl
007d27fa40 tests/conform: Use the clutter stage from mutter
The tests created their own stage, which caused various issues. Lets use
the one from mutter instead.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
01609de587 clutter/stage: Clear pick stack when hiding
Hiding a compositor stage is not something that's really supported, but
will still be used by tests, to get closer to a "fresh" stage for each
test case, when the tests eventually start using the mutter provided
stage.

It'll use that stage simply because creating standalone stages isn't
supported.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
83ee122fad cogl/frame-info: Stop passing the CoglOutput
It's unused, and if it would be, it'd be unreliable, as it'd only be
valid on the Xlib and GLX cogl backends.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
55302dbb38 cursor-renderer: Pass backend to constructor
Then use the backend passed instead of the global singleton.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
7876018755 backends/native: Get clutter backend from backend
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
e3c332fa10 backend: Remove unused freeze/thaw functions
They are no longer used, so remove them.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
faa831f2f6 backend: Remove cursor renderer construction fallback
All backends have their own cursor renderer constuctors, so remove the
unused fallback.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
1a915f06cf clutter: Remove CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD
It was unused, and will simplify things when we're without a master
clock.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
6754195580 clutter/script-parser: Don't skip construct parameters when constructing
The script parser only included G_PARAM_CONSTRUCT_ONLY parameters when
constructing objects. This causes issues if an object requires a
parameter to be set during construction, but may also change after. Fix
this by including G_PARAM_CONSTRUCT parameters when constructing script
objects as well.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
25f9406e69 compositor: Get the stage via the backend
We would get the MetaDisplay from the backend singleton before creating
the MetaCompositor, then in MetaCompositor, get the backend singleton
again to get the stage. To get rid of the extra singleton fetching, just
pass the backend the MetaCompositor constructors, and fetch the stage
directly from the backend everytime it's needed.

This also makes it available earlier than before, as we didn't set our
instance private stage pointer until the manage() call.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:27 +00:00
Jonas Ådahl
9fc428f2e7 clutter/stage: Remove unused function clutter_stage_ensure_redraw()
Not used by anything, and redraws are eventually not going to be stage
global anyway.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
a05dd813da clutter/timeline: Remove clutter_timeline_clone()
It was deprecated long ago, and users should switch to using te regular
constructors.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
08b30d6fe2 clutter/timeline: Remove deprecated 'loop' property
It was since long ago replaced by a 'repeat-count' property.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
84f55d38dd clutter/pan-action: Clean up line lengths
The file stood out and was hard to read because lines were very long
compared to the rest of clutter and mutter. Clean that up by cutting
lines into pieces where appropriate.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
75b5e079cf clutter/timeline: Add meaning to constructor argument variable name
Start follow the convention used in ClutterFrameClock by including the
meaning as well as time granularity in the variable name. The
constructor takes the intended duration of the constructed timeline in
milli seconds, so call the constructor argument `duration_ms`. This is
done in preparation for adding more constuctors.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
d742f9331c tests/clutter: Port timeline-rewind to current test suite
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
420ca31f0b tests/clutter: Port timeline-progress to current test suite
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
73da901cd3 tests/clutter: Port timeline-interpolate to current test suite
The error tolerance is increased dramatically to make the test less
flaky when running in CI.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
dd16fac0c7 tests/clutter: Port timeline tests to current test suite
Also fix a test that dependends on a specific element order in a list
that wasn't defined to have any particular order.

The frames per second is decreased from 30 to 10, to make the test less
flaky when running in CI.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
1b2af2891f tests/clutter/conform: Default to print test logs
To change to the old behavior, pass --quiet. The aim is to be make it
easier to debug issues only reproducing in the CI.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
050c21c24f tests/clutter/conform: Don't run tests in parallel
Might end up failing to acquire D-Bus names, resulting in warnings.
Avoid that by not running the tests in parallel.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1289
2020-06-05 21:39:26 +00:00
Jonas Ådahl
7b45de941b tests/test-client: Disable shadow for Wayland client too
The shadow was disabled for the X11 client as it was far to unreliable
when comparing sizes.

It seems that the Wayland backend has been somewhat unreliable as well,
where some race condition causing incorrect sizes thus a flaky test.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1288
2020-06-05 00:15:52 +02:00
Jonas Ådahl
8d84449941 test-runner: Wait before finding MetaWindow when showing
A "show" command calls gtk_window_show() and gdk_display_sync(), then
returns. This means that the X11 window objects are guaranteed to have
been created in the X11 server.

After that, the test runner will look up the window's associated
MetaWindow and wait for it to be shown.

What this doesn't account for is if mutter didn't get enough CPU time to
see the new window. When this happens, the 'default-size' stacking test
sometimes failed after hiding and showing the X11 window.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1288
2020-06-05 00:15:52 +02:00
193 changed files with 6415 additions and 4882 deletions

View File

@@ -60,17 +60,6 @@ static const gchar * cally_util_get_toolkit_name (void);
static const gchar * cally_util_get_toolkit_version (void);
/* private */
static void cally_util_simulate_snooper_install (void);
static void cally_util_simulate_snooper_remove (void);
static gboolean cally_key_snooper (ClutterActor *actor,
ClutterEvent *event,
gpointer user_data);
static void cally_util_stage_added_cb (ClutterStageManager *stage_manager,
ClutterStage *stage,
gpointer data);
static void cally_util_stage_removed_cb (ClutterStageManager *stage_manager,
ClutterStage *stage,
gpointer data);
static gboolean notify_hf (gpointer key,
gpointer value,
gpointer data);
@@ -153,12 +142,8 @@ cally_util_add_key_event_listener (AtkKeySnoopFunc listener,
CallyKeyEventInfo *event_info = NULL;
if (!key_listener_list)
{
key_listener_list = g_hash_table_new_full (NULL, NULL, NULL, g_free);
cally_util_simulate_snooper_install ();
}
event_info = g_new (CallyKeyEventInfo, 1);
event_info->listener = listener;
event_info->func_data = data;
@@ -179,75 +164,11 @@ cally_util_remove_key_event_listener (guint remove_listener)
{
g_hash_table_destroy (key_listener_list);
key_listener_list = NULL;
cally_util_simulate_snooper_remove ();
}
}
/* ------------------------------ PRIVATE FUNCTIONS ------------------------- */
/* Trying to emulate gtk_key_snooper install (a kind of wrapper). This
could be implemented without it, but I will maintain it in this
way, so if in the future clutter implements it natively it would be
easier the transition */
static void
cally_util_simulate_snooper_install (void)
{
ClutterStageManager *stage_manager = NULL;
ClutterStage *stage = NULL;
GSList *stage_list = NULL;
GSList *iter = NULL;
stage_manager = clutter_stage_manager_get_default ();
stage_list = clutter_stage_manager_list_stages (stage_manager);
for (iter = stage_list; iter != NULL; iter = g_slist_next (iter))
{
stage = CLUTTER_STAGE (iter->data);
g_signal_connect (G_OBJECT (stage), "captured-event",
G_CALLBACK (cally_key_snooper), NULL);
}
g_signal_connect (G_OBJECT (stage_manager), "stage-added",
G_CALLBACK (cally_util_stage_added_cb), cally_key_snooper);
g_signal_connect (G_OBJECT (stage_manager), "stage-removed",
G_CALLBACK (cally_util_stage_removed_cb), cally_key_snooper);
g_slist_free (stage_list);
}
static void
cally_util_simulate_snooper_remove (void)
{
ClutterStageManager *stage_manager = NULL;
ClutterStage *stage = NULL;
GSList *stage_list = NULL;
GSList *iter = NULL;
gint num = 0;
stage_manager = clutter_stage_manager_get_default ();
stage_list = clutter_stage_manager_list_stages (stage_manager);
for (iter = stage_list; iter != NULL; iter = g_slist_next (iter))
{
stage = CLUTTER_STAGE (iter->data);
num += g_signal_handlers_disconnect_by_func (stage, cally_key_snooper, NULL);
}
g_signal_handlers_disconnect_by_func (G_OBJECT (stage_manager),
G_CALLBACK (cally_util_stage_added_cb),
cally_key_snooper);
g_signal_handlers_disconnect_by_func (G_OBJECT (stage_manager),
G_CALLBACK (cally_util_stage_removed_cb),
cally_key_snooper);
#ifdef CALLY_DEBUG
g_print ("Number of snooper callbacks disconnected: %i\n", num);
#endif
}
static AtkKeyEventStruct *
atk_key_event_from_clutter_event_key (ClutterKeyEvent *clutter_event,
gunichar password_char)
@@ -384,59 +305,34 @@ check_key_visibility (ClutterEvent *event)
return DEFAULT_PASSWORD_CHAR;
}
static gboolean
cally_key_snooper (ClutterActor *actor,
ClutterEvent *event,
gpointer user_data)
gboolean
cally_snoop_key_event (ClutterKeyEvent *key)
{
ClutterEvent *event = (ClutterEvent *) key;
AtkKeyEventStruct *key_event = NULL;
gint consumed = 0;
gboolean consumed = FALSE;
gunichar password_char = 0;
/* filter key events */
if ((event->type != CLUTTER_KEY_PRESS) && (event->type != CLUTTER_KEY_RELEASE))
{
return FALSE;
}
password_char = check_key_visibility (event);
return FALSE;
if (key_listener_list)
{
GHashTable *new_hash = g_hash_table_new (NULL, NULL);
g_hash_table_foreach (key_listener_list, insert_hf, new_hash);
key_event = atk_key_event_from_clutter_event_key ((ClutterKeyEvent *)event,
password_char);
password_char = check_key_visibility (event);
key_event = atk_key_event_from_clutter_event_key (key, password_char);
/* func data is inside the hash table */
consumed = g_hash_table_foreach_steal (new_hash, notify_hf, key_event);
consumed = g_hash_table_foreach_steal (new_hash, notify_hf, key_event) > 0;
g_hash_table_destroy (new_hash);
g_free (key_event->string);
g_free (key_event);
}
return (consumed ? 1 : 0);
}
static void
cally_util_stage_added_cb (ClutterStageManager *stage_manager,
ClutterStage *stage,
gpointer data)
{
GCallback cally_key_snooper_cb = G_CALLBACK (data);
g_signal_connect (G_OBJECT (stage), "captured-event", cally_key_snooper_cb, NULL);
}
static void
cally_util_stage_removed_cb (ClutterStageManager *stage_manager,
ClutterStage *stage,
gpointer data)
{
GCallback cally_key_snooper_cb = G_CALLBACK (data);
g_signal_handlers_disconnect_by_func (stage, cally_key_snooper_cb, NULL);
return consumed;
}
void

View File

@@ -79,6 +79,8 @@ GType cally_util_get_type (void) G_GNUC_CONST;
void _cally_util_override_atk_util (void);
gboolean cally_snoop_key_event (ClutterKeyEvent *key);
G_END_DECLS
#endif /* __CALLY_UTIL_H__ */

View File

@@ -615,6 +615,32 @@ clutter_actor_box_scale (ClutterActorBox *box,
box->y2 *= scale;
}
/**
* clutter_actor_box_is_initialized:
* @box: a #ClutterActorBox
*
* Checks if @box has been initialized, a #ClutterActorBox is uninitialized
* if it has a size of -1 at an origin of 0, 0.
*
* Returns: %TRUE if the box is uninitialized, %FALSE if it isn't
*/
gboolean
clutter_actor_box_is_initialized (ClutterActorBox *box)
{
gboolean x1_uninitialized, x2_uninitialized;
gboolean y1_uninitialized, y2_uninitialized;
g_return_val_if_fail (box != NULL, TRUE);
x1_uninitialized = isinf (box->x1);
x2_uninitialized = isinf (box->x2) && signbit (box->x2);
y1_uninitialized = isinf (box->y1);
y2_uninitialized = isinf (box->y2) && signbit (box->y2);
return !x1_uninitialized || !x2_uninitialized ||
!y1_uninitialized || !y2_uninitialized;
}
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterActorBox, clutter_actor_box,
clutter_actor_box_copy,
clutter_actor_box_free,

View File

@@ -313,7 +313,7 @@ void _clutter_actor_detach_clone
void _clutter_actor_queue_redraw_on_clones (ClutterActor *actor);
void _clutter_actor_queue_relayout_on_clones (ClutterActor *actor);
void _clutter_actor_queue_only_relayout (ClutterActor *actor);
void _clutter_actor_queue_update_resource_scale_recursive (ClutterActor *actor);
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor);
gboolean _clutter_actor_get_real_resource_scale (ClutterActor *actor,
float *resource_scale);
@@ -321,6 +321,8 @@ gboolean _clutter_actor_get_real_resource_scale
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
CoglTexture *texture);
void clutter_actor_update_stage_views (ClutterActor *self);
G_END_DECLS
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */

View File

@@ -446,7 +446,8 @@
* ]|
*
* - the initial `@` is mandatory
* - the `section` fragment can be one between "actions", "constraints" and "effects"
* - the `section` fragment can be one between "actions", "constraints", "content",
* and "effects"
* - the `meta-name` fragment is the name of the action, effect, or constraint, as
* specified by the #ClutterActorMeta:name property of #ClutterActorMeta
* - the `property-name` fragment is the name of the action, effect, or constraint
@@ -811,6 +812,9 @@ struct _ClutterActorPrivate
gulong resolution_changed_id;
gulong font_changed_id;
gulong layout_changed_id;
GList *stage_views;
/* bitfields: KEEP AT THE END */
@@ -854,6 +858,7 @@ struct _ClutterActorPrivate
guint had_effects_on_last_paint_volume_update : 1;
guint needs_compute_resource_scale : 1;
guint absolute_origin_changed : 1;
guint needs_update_stage_views : 1;
};
enum
@@ -1016,6 +1021,7 @@ enum
TRANSITIONS_COMPLETED,
TOUCH_EVENT,
TRANSITION_STOPPED,
STAGE_VIEWS_CHANGED,
LAST_SIGNAL
};
@@ -1613,6 +1619,22 @@ clutter_actor_update_map_state (ClutterActor *self,
#endif
}
static void
queue_update_stage_views (ClutterActor *actor)
{
while (actor && !actor->priv->needs_update_stage_views)
{
actor->priv->needs_update_stage_views = TRUE;
/* We don't really need to update the stage-views of the actors up the
* hierarchy, we set the flag anyway though so we can avoid traversing
* the whole scenegraph when looking for actors which need an update
* in clutter_actor_update_stage_views().
*/
actor = actor->priv->parent;
}
}
static void
clutter_actor_real_map (ClutterActor *self)
{
@@ -1627,6 +1649,18 @@ clutter_actor_real_map (ClutterActor *self)
self->priv->needs_paint_volume_update = TRUE;
/* We skip unmapped actors when updating the stage-views list, so if
* an actors list got invalidated while it was unmapped make sure to
* set priv->needs_update_stage_views to TRUE for all actors up the
* hierarchy now.
*/
if (self->priv->needs_update_stage_views)
{
/* Avoid the early return in queue_update_stage_views() */
self->priv->needs_update_stage_views = FALSE;
queue_update_stage_views (self);
}
clutter_actor_ensure_resource_scale (self);
/* notify on parent mapped before potentially mapping
@@ -2409,8 +2443,7 @@ clutter_actor_real_get_preferred_width (ClutterActor *self,
{
ClutterActorPrivate *priv = self->priv;
if (priv->n_children != 0 &&
priv->layout_manager != NULL)
if (priv->layout_manager != NULL)
{
ClutterContainer *container = CLUTTER_CONTAINER (self);
@@ -2449,8 +2482,7 @@ clutter_actor_real_get_preferred_height (ClutterActor *self,
{
ClutterActorPrivate *priv = self->priv;
if (priv->n_children != 0 &&
priv->layout_manager != NULL)
if (priv->layout_manager != NULL)
{
ClutterContainer *container = CLUTTER_CONTAINER (self);
@@ -2564,6 +2596,7 @@ static void
absolute_allocation_changed (ClutterActor *actor)
{
actor->priv->needs_compute_resource_scale = TRUE;
queue_update_stage_views (actor);
}
static ClutterActorTraverseVisitFlags
@@ -4281,6 +4314,7 @@ typedef enum
REMOVE_CHILD_FLUSH_QUEUE = 1 << 4,
REMOVE_CHILD_NOTIFY_FIRST_LAST = 1 << 5,
REMOVE_CHILD_STOP_TRANSITIONS = 1 << 6,
REMOVE_CHILD_CLEAR_STAGE_VIEWS = 1 << 7,
/* default flags for public API */
REMOVE_CHILD_DEFAULT_FLAGS = REMOVE_CHILD_STOP_TRANSITIONS |
@@ -4289,14 +4323,16 @@ typedef enum
REMOVE_CHILD_EMIT_ACTOR_REMOVED |
REMOVE_CHILD_CHECK_STATE |
REMOVE_CHILD_FLUSH_QUEUE |
REMOVE_CHILD_NOTIFY_FIRST_LAST,
REMOVE_CHILD_NOTIFY_FIRST_LAST |
REMOVE_CHILD_CLEAR_STAGE_VIEWS,
/* flags for legacy/deprecated API */
REMOVE_CHILD_LEGACY_FLAGS = REMOVE_CHILD_STOP_TRANSITIONS |
REMOVE_CHILD_CHECK_STATE |
REMOVE_CHILD_FLUSH_QUEUE |
REMOVE_CHILD_EMIT_PARENT_SET |
REMOVE_CHILD_NOTIFY_FIRST_LAST
REMOVE_CHILD_NOTIFY_FIRST_LAST |
REMOVE_CHILD_CLEAR_STAGE_VIEWS
} ClutterActorRemoveChildFlags;
/*< private >
@@ -4318,6 +4354,7 @@ clutter_actor_remove_child_internal (ClutterActor *self,
gboolean notify_first_last;
gboolean was_mapped;
gboolean stop_transitions;
gboolean clear_stage_views;
GObject *obj;
if (self == child)
@@ -4334,6 +4371,7 @@ clutter_actor_remove_child_internal (ClutterActor *self,
flush_queue = (flags & REMOVE_CHILD_FLUSH_QUEUE) != 0;
notify_first_last = (flags & REMOVE_CHILD_NOTIFY_FIRST_LAST) != 0;
stop_transitions = (flags & REMOVE_CHILD_STOP_TRANSITIONS) != 0;
clear_stage_views = (flags & REMOVE_CHILD_CLEAR_STAGE_VIEWS) != 0;
obj = G_OBJECT (self);
g_object_freeze_notify (obj);
@@ -4407,6 +4445,13 @@ clutter_actor_remove_child_internal (ClutterActor *self,
clutter_actor_queue_compute_expand (self);
}
/* Only actors which are attached to a stage get notified about changes
* to the stage views, so make sure all the stage-views lists are
* cleared as the child and its children leave the actor tree.
*/
if (clear_stage_views && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
clutter_actor_clear_stage_views_recursive (child);
if (emit_parent_set && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
{
child->priv->needs_compute_resource_scale = TRUE;
@@ -5197,7 +5242,7 @@ clutter_actor_set_property (GObject *object,
break;
case PROP_OFFSCREEN_REDIRECT:
clutter_actor_set_offscreen_redirect (actor, g_value_get_enum (value));
clutter_actor_set_offscreen_redirect (actor, g_value_get_flags (value));
break;
case PROP_NAME:
@@ -6062,6 +6107,7 @@ clutter_actor_dispose (GObject *object)
if (priv->layout_manager != NULL)
{
g_clear_signal_handler (&priv->layout_changed_id, priv->layout_manager);
clutter_layout_manager_set_container (priv->layout_manager, NULL);
g_clear_object (&priv->layout_manager);
}
@@ -6078,6 +6124,8 @@ clutter_actor_dispose (GObject *object)
priv->clones = NULL;
}
g_clear_pointer (&priv->stage_views, g_list_free);
G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object);
}
@@ -8614,6 +8662,27 @@ clutter_actor_class_init (ClutterActorClass *klass)
g_signal_set_va_marshaller (actor_signals[TOUCH_EVENT],
G_TYPE_FROM_CLASS (object_class),
_clutter_marshal_BOOLEAN__BOXEDv);
/**
* ClutterActor::stage-views-changed:
* @actor: a #ClutterActor
*
* The ::stage-views-changed signal is emitted when the position or
* size an actor is being painted at have changed so that it's visible
* on different stage views.
*
* This signal is also emitted when the actor gets detached from the stage
* or when the views of the stage have been invalidated and will be
* replaced; it's not emitted when the actor gets hidden.
*/
actor_signals[STAGE_VIEWS_CHANGED] =
g_signal_new (I_("stage-views-changed"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
static void
@@ -8623,6 +8692,8 @@ clutter_actor_init (ClutterActor *self)
self->priv = priv = clutter_actor_get_instance_private (self);
priv->allocation = (ClutterActorBox) CLUTTER_ACTOR_BOX_UNINITIALIZED;
priv->opacity = 0xff;
priv->show_on_set_parent = TRUE;
priv->resource_scale = -1.0f;
@@ -8632,6 +8703,7 @@ clutter_actor_init (ClutterActor *self)
priv->needs_allocation = TRUE;
priv->needs_paint_volume_update = TRUE;
priv->needs_compute_resource_scale = TRUE;
priv->needs_update_stage_views = TRUE;
priv->cached_width_age = 1;
priv->cached_height_age = 1;
@@ -13605,138 +13677,107 @@ clutter_actor_set_child_at_index (ClutterActor *self,
gboolean
clutter_actor_event (ClutterActor *actor,
const ClutterEvent *event,
gboolean capture)
gboolean capture)
{
gboolean retval = FALSE;
gint signal_num = -1;
GQuark detail = 0;
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
g_object_ref (actor);
switch (event->type)
{
case CLUTTER_NOTHING:
break;
case CLUTTER_BUTTON_PRESS:
signal_num = BUTTON_PRESS_EVENT;
detail = quark_button;
break;
case CLUTTER_BUTTON_RELEASE:
signal_num = BUTTON_RELEASE_EVENT;
detail = quark_button;
break;
case CLUTTER_SCROLL:
signal_num = SCROLL_EVENT;
detail = quark_scroll;
break;
case CLUTTER_KEY_PRESS:
signal_num = KEY_PRESS_EVENT;
detail = quark_key;
break;
case CLUTTER_KEY_RELEASE:
signal_num = KEY_RELEASE_EVENT;
detail = quark_key;
break;
case CLUTTER_MOTION:
signal_num = MOTION_EVENT;
detail = quark_motion;
break;
case CLUTTER_ENTER:
signal_num = ENTER_EVENT;
detail = quark_pointer_focus;
break;
case CLUTTER_LEAVE:
signal_num = LEAVE_EVENT;
detail = quark_pointer_focus;
break;
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_END:
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_CANCEL:
signal_num = TOUCH_EVENT;
detail = quark_touch;
break;
case CLUTTER_TOUCHPAD_PINCH:
case CLUTTER_TOUCHPAD_SWIPE:
signal_num = -1;
detail = quark_touchpad;
break;
case CLUTTER_PROXIMITY_IN:
case CLUTTER_PROXIMITY_OUT:
signal_num = -1;
detail = quark_proximity;
break;
case CLUTTER_PAD_BUTTON_PRESS:
case CLUTTER_PAD_BUTTON_RELEASE:
case CLUTTER_PAD_STRIP:
case CLUTTER_PAD_RING:
signal_num = -1;
detail = quark_pad;
break;
case CLUTTER_DELETE:
signal_num = -1;
detail = quark_delete;
break;
case CLUTTER_DESTROY_NOTIFY:
signal_num = -1;
detail = quark_destroy;
break;
case CLUTTER_CLIENT_MESSAGE:
signal_num = -1;
detail = quark_client;
break;
case CLUTTER_STAGE_STATE:
signal_num = -1;
detail = quark_stage;
break;
case CLUTTER_EVENT_LAST: /* Just keep compiler warnings quiet */
break;
}
if (capture)
g_signal_emit (actor, actor_signals[CAPTURED_EVENT], detail, event, &retval);
else
{
GQuark detail = 0;
g_signal_emit (actor, actor_signals[EVENT], 0, event, &retval);
switch (event->type)
{
case CLUTTER_NOTHING:
break;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
detail = quark_key;
break;
case CLUTTER_MOTION:
detail = quark_motion;
break;
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
detail = quark_pointer_focus;
break;
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
detail = quark_button;
break;
case CLUTTER_SCROLL:
detail = quark_scroll;
break;
case CLUTTER_STAGE_STATE:
detail = quark_stage;
break;
case CLUTTER_DESTROY_NOTIFY:
detail = quark_destroy;
break;
case CLUTTER_CLIENT_MESSAGE:
detail = quark_client;
break;
case CLUTTER_DELETE:
detail = quark_delete;
break;
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_END:
case CLUTTER_TOUCH_CANCEL:
detail = quark_touch;
break;
case CLUTTER_TOUCHPAD_PINCH:
case CLUTTER_TOUCHPAD_SWIPE:
detail = quark_touchpad;
break;
case CLUTTER_PROXIMITY_IN:
case CLUTTER_PROXIMITY_OUT:
detail = quark_proximity;
break;
case CLUTTER_PAD_BUTTON_PRESS:
case CLUTTER_PAD_BUTTON_RELEASE:
case CLUTTER_PAD_STRIP:
case CLUTTER_PAD_RING:
detail = quark_pad;
break;
case CLUTTER_EVENT_LAST: /* Just keep compiler warnings quiet */
break;
}
g_signal_emit (actor,
actor_signals[CAPTURED_EVENT],
detail,
event,
&retval);
goto out;
if (!retval && signal_num != -1)
g_signal_emit (actor, actor_signals[signal_num], 0, event, &retval);
}
g_signal_emit (actor, actor_signals[EVENT], 0, event, &retval);
if (!retval)
{
switch (event->type)
{
case CLUTTER_NOTHING:
break;
case CLUTTER_BUTTON_PRESS:
signal_num = BUTTON_PRESS_EVENT;
break;
case CLUTTER_BUTTON_RELEASE:
signal_num = BUTTON_RELEASE_EVENT;
break;
case CLUTTER_SCROLL:
signal_num = SCROLL_EVENT;
break;
case CLUTTER_KEY_PRESS:
signal_num = KEY_PRESS_EVENT;
break;
case CLUTTER_KEY_RELEASE:
signal_num = KEY_RELEASE_EVENT;
break;
case CLUTTER_MOTION:
signal_num = MOTION_EVENT;
break;
case CLUTTER_ENTER:
signal_num = ENTER_EVENT;
break;
case CLUTTER_LEAVE:
signal_num = LEAVE_EVENT;
break;
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_END:
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_CANCEL:
signal_num = TOUCH_EVENT;
break;
case CLUTTER_DELETE:
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_CLIENT_MESSAGE:
default:
signal_num = -1;
break;
}
if (signal_num != -1)
g_signal_emit (actor, actor_signals[signal_num], 0,
event, &retval);
}
out:
g_object_unref (actor);
return retval;
@@ -14551,6 +14592,37 @@ get_layout_from_animation_property (ClutterActor *actor,
return TRUE;
}
static gboolean
get_content_from_animation_property (ClutterActor *actor,
const gchar *name,
gchar **name_p)
{
g_auto (GStrv) tokens = NULL;
if (!g_str_has_prefix (name, "@content"))
return FALSE;
if (!actor->priv->content)
{
CLUTTER_NOTE (ANIMATION, "No ClutterContent available for '%s'",
name + 1);
return FALSE;
}
tokens = g_strsplit (name, ".", -1);
if (tokens == NULL || g_strv_length (tokens) != 2)
{
CLUTTER_NOTE (ANIMATION, "Invalid property name '%s'",
name + 1);
return FALSE;
}
if (name_p != NULL)
*name_p = g_strdup (tokens[1]);
return TRUE;
}
static ClutterActorMeta *
get_meta_from_animation_property (ClutterActor *actor,
const gchar *name,
@@ -14618,6 +14690,7 @@ clutter_actor_find_property (ClutterAnimatable *animatable,
GObjectClass *klass = NULL;
GParamSpec *pspec = NULL;
gchar *p_name = NULL;
gboolean use_content = FALSE;
gboolean use_layout;
use_layout = get_layout_from_animation_property (actor,
@@ -14625,6 +14698,11 @@ clutter_actor_find_property (ClutterAnimatable *animatable,
&p_name);
if (!use_layout)
use_content = get_content_from_animation_property (actor,
property_name,
&p_name);
if (!use_layout && !use_content)
meta = get_meta_from_animation_property (actor,
property_name,
&p_name);
@@ -14639,6 +14717,12 @@ clutter_actor_find_property (ClutterAnimatable *animatable,
{
klass = G_OBJECT_GET_CLASS (actor->priv->layout_manager);
pspec = g_object_class_find_property (klass, p_name);
}
else if (use_content)
{
klass = G_OBJECT_GET_CLASS (actor->priv->content);
pspec = g_object_class_find_property (klass, p_name);
}
else
@@ -14661,6 +14745,7 @@ clutter_actor_get_initial_state (ClutterAnimatable *animatable,
ClutterActor *actor = CLUTTER_ACTOR (animatable);
ClutterActorMeta *meta = NULL;
gchar *p_name = NULL;
gboolean use_content = FALSE;
gboolean use_layout;
use_layout = get_layout_from_animation_property (actor,
@@ -14668,6 +14753,11 @@ clutter_actor_get_initial_state (ClutterAnimatable *animatable,
&p_name);
if (!use_layout)
use_content = get_content_from_animation_property (actor,
property_name,
&p_name);
if (!use_layout && !use_content)
meta = get_meta_from_animation_property (actor,
property_name,
&p_name);
@@ -14676,6 +14766,8 @@ clutter_actor_get_initial_state (ClutterAnimatable *animatable,
g_object_get_property (G_OBJECT (meta), p_name, initial);
else if (use_layout)
g_object_get_property (G_OBJECT (actor->priv->layout_manager), p_name, initial);
else if (use_content)
g_object_get_property (G_OBJECT (actor->priv->content), p_name, initial);
else
g_object_get_property (G_OBJECT (animatable), property_name, initial);
@@ -14826,6 +14918,7 @@ clutter_actor_set_final_state (ClutterAnimatable *animatable,
ClutterActor *actor = CLUTTER_ACTOR (animatable);
ClutterActorMeta *meta = NULL;
gchar *p_name = NULL;
gboolean use_content = FALSE;
gboolean use_layout;
use_layout = get_layout_from_animation_property (actor,
@@ -14833,6 +14926,11 @@ clutter_actor_set_final_state (ClutterAnimatable *animatable,
&p_name);
if (!use_layout)
use_content = get_content_from_animation_property (actor,
property_name,
&p_name);
if (!use_layout && !use_content)
meta = get_meta_from_animation_property (actor,
property_name,
&p_name);
@@ -14841,6 +14939,8 @@ clutter_actor_set_final_state (ClutterAnimatable *animatable,
g_object_set_property (G_OBJECT (meta), p_name, final);
else if (use_layout)
g_object_set_property (G_OBJECT (actor->priv->layout_manager), p_name, final);
else if (use_content)
g_object_set_property (G_OBJECT (actor->priv->content), p_name, final);
else
{
GObjectClass *obj_class = G_OBJECT_GET_CLASS (animatable);
@@ -17419,17 +17519,27 @@ _clutter_actor_get_resource_scale_for_rect (ClutterActor *self,
float *resource_scale)
{
ClutterActor *stage;
g_autoptr (GList) views = NULL;
GList *l;
float max_scale = 0;
stage = _clutter_actor_get_stage_internal (self);
if (!stage)
return FALSE;
if (!_clutter_stage_get_max_view_scale_factor_for_rect (CLUTTER_STAGE (stage),
bounding_rect,
&max_scale))
views = clutter_stage_get_views_for_rect (CLUTTER_STAGE (stage),
bounding_rect);
if (!views)
return FALSE;
for (l = views; l; l = l->next)
{
ClutterStageView *view = l->data;
max_scale = MAX (clutter_stage_view_get_scale (view), max_scale);
}
*resource_scale = max_scale;
return TRUE;
@@ -17505,20 +17615,29 @@ _clutter_actor_compute_resource_scale (ClutterActor *self,
}
static ClutterActorTraverseVisitFlags
queue_update_resource_scale_cb (ClutterActor *actor,
int depth,
void *user_data)
clear_stage_views_cb (ClutterActor *actor,
int depth,
gpointer user_data)
{
g_autoptr (GList) old_stage_views = NULL;
actor->priv->needs_update_stage_views = TRUE;
actor->priv->needs_compute_resource_scale = TRUE;
old_stage_views = g_steal_pointer (&actor->priv->stage_views);
if (old_stage_views)
g_signal_emit (actor, actor_signals[STAGE_VIEWS_CHANGED], 0);
return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE;
}
void
_clutter_actor_queue_update_resource_scale_recursive (ClutterActor *self)
clutter_actor_clear_stage_views_recursive (ClutterActor *self)
{
_clutter_actor_traverse (self,
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST,
queue_update_resource_scale_cb,
clear_stage_views_cb,
NULL,
NULL);
}
@@ -17610,6 +17729,125 @@ clutter_actor_get_resource_scale (ClutterActor *self,
return FALSE;
}
static gboolean
sorted_lists_equal (GList *list_a,
GList *list_b)
{
GList *a, *b;
if (!list_a && !list_b)
return TRUE;
for (a = list_a, b = list_b;
a && b;
a = a->next, b = b->next)
{
if (a->data != b->data)
break;
if (!a->next && !b->next)
return TRUE;
}
return FALSE;
}
static void
update_stage_views (ClutterActor *self)
{
ClutterActorPrivate *priv = self->priv;
g_autoptr (GList) old_stage_views = NULL;
ClutterStage *stage;
graphene_rect_t bounding_rect;
old_stage_views = g_steal_pointer (&priv->stage_views);
if (priv->needs_allocation)
{
g_warning ("Can't update stage views actor %s is on because it needs an "
"allocation.", _clutter_actor_get_debug_name (self));
goto out;
}
stage = CLUTTER_STAGE (_clutter_actor_get_stage_internal (self));
g_return_if_fail (stage);
clutter_actor_get_transformed_position (self,
&bounding_rect.origin.x,
&bounding_rect.origin.y);
clutter_actor_get_transformed_size (self,
&bounding_rect.size.width,
&bounding_rect.size.height);
if (bounding_rect.size.width == 0.0 ||
bounding_rect.size.height == 0.0)
goto out;
priv->stage_views = clutter_stage_get_views_for_rect (stage,
&bounding_rect);
out:
if (g_signal_has_handler_pending (self, actor_signals[STAGE_VIEWS_CHANGED],
0, TRUE))
{
if (!sorted_lists_equal (old_stage_views, priv->stage_views))
g_signal_emit (self, actor_signals[STAGE_VIEWS_CHANGED], 0);
}
}
void
clutter_actor_update_stage_views (ClutterActor *self)
{
ClutterActorPrivate *priv = self->priv;
ClutterActor *child;
if (!CLUTTER_ACTOR_IS_MAPPED (self) ||
CLUTTER_ACTOR_IN_DESTRUCTION (self))
return;
if (!priv->needs_update_stage_views)
return;
update_stage_views (self);
priv->needs_update_stage_views = FALSE;
for (child = priv->first_child; child; child = child->priv->next_sibling)
clutter_actor_update_stage_views (child);
}
/**
* clutter_actor_peek_stage_views:
* @self: A #ClutterActor
*
* Retrieves the list of #ClutterStageView<!-- -->s the actor is being
* painted on.
*
* If this function is called during the paint cycle, the list is guaranteed
* to be up-to-date, if called outside the paint cycle, the list will
* contain the views the actor was painted on last.
*
* The list returned by this function is not updated when the actors
* visibility changes: If an actor gets hidden and is not being painted
* anymore, this function will return the list of views the actor was
* painted on last.
*
* If an actor is not attached to a stage (realized), this function will
* always return an empty list.
*
* Returns: (transfer none) (element-type Clutter.StageView): The list of
* #ClutterStageView<!-- -->s the actor is being painted on. The list and
* its contents are owned by the #ClutterActor and the list may not be
* freed or modified.
*/
GList *
clutter_actor_peek_stage_views (ClutterActor *self)
{
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
return self->priv->stage_views;
}
/**
* clutter_actor_has_overlaps:
* @self: A #ClutterActor
@@ -17971,9 +18209,7 @@ clutter_actor_set_layout_manager (ClutterActor *self,
if (priv->layout_manager != NULL)
{
g_signal_handlers_disconnect_by_func (priv->layout_manager,
G_CALLBACK (on_layout_manager_changed),
self);
g_clear_signal_handler (&priv->layout_changed_id, priv->layout_manager);
clutter_layout_manager_set_container (priv->layout_manager, NULL);
g_clear_object (&priv->layout_manager);
}
@@ -17985,9 +18221,10 @@ clutter_actor_set_layout_manager (ClutterActor *self,
g_object_ref_sink (priv->layout_manager);
clutter_layout_manager_set_container (priv->layout_manager,
CLUTTER_CONTAINER (self));
g_signal_connect (priv->layout_manager, "layout-changed",
G_CALLBACK (on_layout_manager_changed),
self);
priv->layout_changed_id =
g_signal_connect (priv->layout_manager, "layout-changed",
G_CALLBACK (on_layout_manager_changed),
self);
}
clutter_actor_queue_relayout (self);
@@ -19111,7 +19348,8 @@ should_skip_implicit_transition (ClutterActor *self,
* skip all transitions on the :allocation, to avoid actors "flying in"
* into their new position and size
*/
if (pspec == obj_props[PROP_ALLOCATION] && priv->needs_allocation)
if (pspec == obj_props[PROP_ALLOCATION] &&
!clutter_actor_box_is_initialized (&priv->allocation))
return TRUE;
/* if the actor is not mapped and is not part of a branch of the scene

View File

@@ -919,6 +919,9 @@ void clutter_actor_pick_box (ClutterActor *self,
ClutterPickContext *pick_context,
const ClutterActorBox *box);
CLUTTER_EXPORT
GList * clutter_actor_peek_stage_views (ClutterActor *self);
G_END_DECLS
#endif /* __CLUTTER_ACTOR_H__ */

View File

@@ -58,6 +58,7 @@ struct _ClutterAlignConstraint
ClutterActor *actor;
ClutterActor *source;
ClutterAlignAxis align_axis;
graphene_point_t pivot;
gfloat factor;
};
@@ -72,6 +73,7 @@ enum
PROP_SOURCE,
PROP_ALIGN_AXIS,
PROP_PIVOT_POINT,
PROP_FACTOR,
PROP_LAST
@@ -84,12 +86,11 @@ G_DEFINE_TYPE (ClutterAlignConstraint,
CLUTTER_TYPE_CONSTRAINT);
static void
source_position_changed (ClutterActor *actor,
GParamSpec *pspec,
ClutterAlignConstraint *align)
source_queue_relayout (ClutterActor *actor,
ClutterAlignConstraint *align)
{
if (align->actor != NULL)
clutter_actor_queue_relayout (align->actor);
_clutter_actor_queue_only_relayout (align->actor);
}
static void
@@ -134,35 +135,41 @@ clutter_align_constraint_update_allocation (ClutterConstraint *constraint,
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (constraint);
gfloat source_width, source_height;
gfloat actor_width, actor_height;
gfloat source_x, source_y;
gfloat offset_x_start, offset_y_start;
gfloat pivot_x, pivot_y;
if (align->source == NULL)
return;
clutter_actor_box_get_size (allocation, &actor_width, &actor_height);
clutter_actor_get_position (align->source, &source_x, &source_y);
clutter_actor_get_size (align->source, &source_width, &source_height);
pivot_x = align->pivot.x == -1.f
? align->factor
: align->pivot.x;
pivot_y = align->pivot.y == -1.f
? align->factor
: align->pivot.y;
offset_x_start = pivot_x * -actor_width;
offset_y_start = pivot_y * -actor_height;
switch (align->align_axis)
{
case CLUTTER_ALIGN_X_AXIS:
allocation->x1 = ((source_width - actor_width) * align->factor)
+ source_x;
allocation->x1 += offset_x_start + (source_width * align->factor);
allocation->x2 = allocation->x1 + actor_width;
break;
case CLUTTER_ALIGN_Y_AXIS:
allocation->y1 = ((source_height - actor_height) * align->factor)
+ source_y;
allocation->y1 += offset_y_start + (source_height * align->factor);
allocation->y2 = allocation->y1 + actor_height;
break;
case CLUTTER_ALIGN_BOTH:
allocation->x1 = ((source_width - actor_width) * align->factor)
+ source_x;
allocation->y1 = ((source_height - actor_height) * align->factor)
+ source_y;
allocation->x1 += offset_x_start + (source_width * align->factor);
allocation->y1 += offset_y_start + (source_height * align->factor);
allocation->x2 = allocation->x1 + actor_width;
allocation->y2 = allocation->y1 + actor_height;
break;
@@ -186,7 +193,7 @@ clutter_align_constraint_dispose (GObject *gobject)
G_CALLBACK (source_destroyed),
align);
g_signal_handlers_disconnect_by_func (align->source,
G_CALLBACK (source_position_changed),
G_CALLBACK (source_queue_relayout),
align);
align->source = NULL;
}
@@ -212,6 +219,10 @@ clutter_align_constraint_set_property (GObject *gobject,
clutter_align_constraint_set_align_axis (align, g_value_get_enum (value));
break;
case PROP_PIVOT_POINT:
clutter_align_constraint_set_pivot_point (align, g_value_get_boxed (value));
break;
case PROP_FACTOR:
clutter_align_constraint_set_factor (align, g_value_get_float (value));
break;
@@ -240,6 +251,16 @@ clutter_align_constraint_get_property (GObject *gobject,
g_value_set_enum (value, align->align_axis);
break;
case PROP_PIVOT_POINT:
{
graphene_point_t point;
clutter_align_constraint_get_pivot_point (align, &point);
g_value_set_boxed (value, &point);
}
break;
case PROP_FACTOR:
g_value_set_float (value, align->factor);
break;
@@ -293,6 +314,30 @@ clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass)
CLUTTER_ALIGN_X_AXIS,
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT);
/**
* ClutterAlignConstraint:pivot-point:
*
* The pivot point used by the constraint. The pivot point is the
* point in the constraint actor around which the aligning is applied,
* with (0, 0) being the top left corner of the actor and (1, 1) the
* bottom right corner of the actor.
*
* For example, setting the pivot point to (0.5, 0.5) and using a factor
* of 1 for both axes will align the actors horizontal and vertical
* center point with the bottom right corner of the source actor.
*
* By default, the pivot point is set to (-1, -1), which means it's not
* used and the constrained actor will be aligned to always stay inside
* the source actor.
*/
obj_props[PROP_PIVOT_POINT] =
g_param_spec_boxed ("pivot-point",
P_("Pivot point"),
P_("The pivot point"),
GRAPHENE_TYPE_POINT,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
/**
* ClutterAlignConstraint:factor:
*
@@ -325,6 +370,8 @@ clutter_align_constraint_init (ClutterAlignConstraint *self)
self->actor = NULL;
self->source = NULL;
self->align_axis = CLUTTER_ALIGN_X_AXIS;
self->pivot.x = -1.f;
self->pivot.y = -1.f;
self->factor = 0.0f;
}
@@ -402,15 +449,15 @@ clutter_align_constraint_set_source (ClutterAlignConstraint *align,
G_CALLBACK (source_destroyed),
align);
g_signal_handlers_disconnect_by_func (old_source,
G_CALLBACK (source_position_changed),
G_CALLBACK (source_queue_relayout),
align);
}
align->source = source;
if (align->source != NULL)
{
g_signal_connect (align->source, "notify::allocation",
G_CALLBACK (source_position_changed),
g_signal_connect (align->source, "queue-relayout",
G_CALLBACK (source_queue_relayout),
align);
g_signal_connect (align->source, "destroy",
G_CALLBACK (source_destroyed),
@@ -487,6 +534,60 @@ clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align)
return align->align_axis;
}
/**
* clutter_align_constraint_set_pivot_point:
* @align: a #ClutterAlignConstraint
* @pivot_point: A #GraphenePoint
*
* Sets the pivot point used by the constraint, the pivot point is the
* point in the constraint actor around which the aligning is applied,
* with (0, 0) being the top left corner of the actor and (1, 1) the
* bottom right corner of the actor.
*
* If -1 is used, the pivot point is unset and the constrained actor
* will be aligned to always stay inside the source actor.
*/
void
clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align,
const graphene_point_t *pivot_point)
{
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
g_return_if_fail (pivot_point != NULL);
g_return_if_fail (pivot_point->x == -1.f ||
(pivot_point->x >= 0.f && pivot_point->x <= 1.f));
g_return_if_fail (pivot_point->y == -1.f ||
(pivot_point->y >= 0.f && pivot_point->y <= 1.f));
if (graphene_point_equal (&align->pivot, pivot_point))
return;
align->pivot = *pivot_point;
if (align->actor != NULL)
clutter_actor_queue_relayout (align->actor);
g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_PIVOT_POINT]);
}
/**
* clutter_align_constraint_get_pivot_point
* @align: a #ClutterAlignConstraint
* @pivot_point: (out caller-allocates): return location for a #GraphenePoint
*
* Gets the pivot point used by the constraint set with
* clutter_align_constraint_set_pivot_point(). If no custom pivot
* point is set, -1 is set.
*/
void
clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align,
graphene_point_t *pivot_point)
{
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
g_return_if_fail (pivot_point != NULL);
*pivot_point = align->pivot;
}
/**
* clutter_align_constraint_set_factor:
* @align: a #ClutterAlignConstraint

View File

@@ -67,6 +67,12 @@ void clutter_align_constraint_set_align_axis (ClutterAlignConstrai
CLUTTER_EXPORT
ClutterAlignAxis clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align);
CLUTTER_EXPORT
void clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align,
const graphene_point_t *pivot_point);
CLUTTER_EXPORT
void clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align,
graphene_point_t *pivot_point);
CLUTTER_EXPORT
void clutter_align_constraint_set_factor (ClutterAlignConstraint *align,
gfloat factor);
CLUTTER_EXPORT

View File

@@ -165,6 +165,9 @@ clutter_bind_constraint_update_preferred_size (ClutterConstraint *constraint,
bind->coordinate == CLUTTER_BIND_ALL))
return;
if (clutter_actor_contains (bind->source, actor))
return;
switch (direction)
{
case CLUTTER_ORIENTATION_HORIZONTAL:

View File

@@ -52,6 +52,8 @@
struct _ClutterClonePrivate
{
ClutterActor *clone_source;
float x_scale, y_scale;
gulong source_destroy_id;
};
@@ -122,8 +124,6 @@ static void
clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
{
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorBox box, source_box;
gfloat x_scale, y_scale;
/* First chain up and apply all the standard ClutterActor
* transformations... */
@@ -134,21 +134,7 @@ clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
if (priv->clone_source == NULL)
return;
/* get our allocated size */
clutter_actor_get_allocation_box (self, &box);
/* and get the allocated size of the source */
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
/* We need to scale what the clone-source actor paints to fill our own
* allocation...
*/
x_scale = clutter_actor_box_get_width (&box)
/ clutter_actor_box_get_width (&source_box);
y_scale = clutter_actor_box_get_height (&box)
/ clutter_actor_box_get_height (&source_box);
cogl_matrix_scale (matrix, x_scale, y_scale, x_scale);
cogl_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
}
static void
@@ -244,6 +230,8 @@ clutter_clone_allocate (ClutterActor *self,
{
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorClass *parent_class;
ClutterActorBox source_box;
float x_scale, y_scale;
/* chain up */
parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class);
@@ -259,6 +247,23 @@ clutter_clone_allocate (ClutterActor *self,
!clutter_actor_has_allocation (priv->clone_source))
clutter_actor_allocate_preferred_size (priv->clone_source);
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
/* We need to scale what the clone-source actor paints to fill our own
* allocation...
*/
x_scale = clutter_actor_box_get_width (box)
/ clutter_actor_box_get_width (&source_box);
y_scale = clutter_actor_box_get_height (box)
/ clutter_actor_box_get_height (&source_box);
if (!G_APPROX_VALUE (priv->x_scale, x_scale, FLT_EPSILON) ||
!G_APPROX_VALUE (priv->y_scale, y_scale, FLT_EPSILON))
{
priv->x_scale = x_scale;
priv->y_scale = y_scale;
}
#if 0
/* XXX - this is wrong: ClutterClone cannot clone unparented
* actors, as it will break all invariants
@@ -364,6 +369,9 @@ static void
clutter_clone_init (ClutterClone *self)
{
self->priv = clutter_clone_get_instance_private (self);
self->priv->x_scale = 1.f;
self->priv->y_scale = 1.f;
}
/**

View File

@@ -1317,8 +1317,6 @@ typedef enum
* painting the stages
* @CLUTTER_REPAINT_FLAGS_POST_PAINT: Run the repaint function after
* painting the stages
* @CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD: Ensure that a new frame
* is queued after adding the repaint function
*
* Flags to pass to clutter_threads_add_repaint_func_full().
*
@@ -1328,7 +1326,6 @@ typedef enum
{
CLUTTER_REPAINT_FLAGS_PRE_PAINT = 1 << 0,
CLUTTER_REPAINT_FLAGS_POST_PAINT = 1 << 1,
CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD = 1 << 2
} ClutterRepaintFlags;
/**

View File

@@ -692,20 +692,6 @@ _clutter_input_device_free_touch_info (gpointer data)
g_slice_free (ClutterTouchInfo, data);
}
static ClutterActor *
_clutter_input_device_get_actor (ClutterInputDevice *device,
ClutterEventSequence *sequence)
{
ClutterTouchInfo *info;
if (sequence == NULL)
return device->cursor_actor;
info = g_hash_table_lookup (device->touch_sequences_info, sequence);
return info->actor;
}
static void
_clutter_input_device_associate_actor (ClutterInputDevice *device,
ClutterEventSequence *sequence,
@@ -815,7 +801,7 @@ _clutter_input_device_set_actor (ClutterInputDevice *device,
ClutterActor *actor,
gboolean emit_crossing)
{
ClutterActor *old_actor = _clutter_input_device_get_actor (device, sequence);
ClutterActor *old_actor = clutter_input_device_get_actor (device, sequence);
if (old_actor == actor)
return;
@@ -850,7 +836,7 @@ _clutter_input_device_set_actor (ClutterInputDevice *device,
}
/* processing the event might have destroyed the actor */
tmp_old_actor = _clutter_input_device_get_actor (device, sequence);
tmp_old_actor = clutter_input_device_get_actor (device, sequence);
_clutter_input_device_unassociate_actor (device,
old_actor,
tmp_old_actor == NULL);
@@ -1054,7 +1040,7 @@ clutter_input_device_update (ClutterInputDevice *device,
clutter_input_device_get_coords (device, sequence, &point);
old_cursor_actor = _clutter_input_device_get_actor (device, sequence);
old_cursor_actor = clutter_input_device_get_actor (device, sequence);
new_cursor_actor =
_clutter_stage_do_pick (stage, point.x, point.y, CLUTTER_PICK_REACTIVE);
@@ -1085,22 +1071,33 @@ clutter_input_device_update (ClutterInputDevice *device,
}
/**
* clutter_input_device_get_pointer_actor:
* @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
* clutter_input_device_get_actor:
* @device: a #ClutterInputDevice
* @sequence: (allow-none): an optional #ClutterEventSequence
*
* Retrieves the #ClutterActor underneath the pointer of @device
* Retrieves the #ClutterActor underneath the pointer or touchpoint
* of @device and @sequence.
*
* Return value: (transfer none): a pointer to the #ClutterActor or %NULL
*
* Since: 1.2
*/
ClutterActor *
clutter_input_device_get_pointer_actor (ClutterInputDevice *device)
clutter_input_device_get_actor (ClutterInputDevice *device,
ClutterEventSequence *sequence)
{
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL);
ClutterTouchInfo *info;
return device->cursor_actor;
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
if (sequence == NULL)
return device->cursor_actor;
info = g_hash_table_lookup (device->touch_sequences_info, sequence);
g_return_val_if_fail (info != NULL, NULL);
return info->actor;
}
/**

View File

@@ -92,7 +92,8 @@ gboolean clutter_input_device_get_coords (ClutterInputDevi
CLUTTER_EXPORT
ClutterModifierType clutter_input_device_get_modifier_state (ClutterInputDevice *device);
CLUTTER_EXPORT
ClutterActor * clutter_input_device_get_pointer_actor (ClutterInputDevice *device);
ClutterActor * clutter_input_device_get_actor (ClutterInputDevice *device,
ClutterEventSequence *sequence);
CLUTTER_EXPORT
ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device);
CLUTTER_EXPORT

View File

@@ -1653,6 +1653,8 @@ static inline void
emit_keyboard_event (ClutterEvent *event,
ClutterInputDevice *device)
{
cally_snoop_key_event ((ClutterKeyEvent *) event);
if (_clutter_event_process_filters (event))
return;
@@ -2049,7 +2051,8 @@ _clutter_process_event_details (ClutterActor *stage,
emit_touch_event (event, device);
if (event->type == CLUTTER_TOUCH_END)
if (event->type == CLUTTER_TOUCH_END ||
event->type == CLUTTER_TOUCH_CANCEL)
_clutter_input_device_remove_event_sequence (device, event);
break;
@@ -2084,7 +2087,8 @@ _clutter_process_event_details (ClutterActor *stage,
emit_touch_event (event, device);
if (event->type == CLUTTER_TOUCH_END)
if (event->type == CLUTTER_TOUCH_END ||
event->type == CLUTTER_TOUCH_CANCEL)
_clutter_input_device_remove_event_sequence (device, event);
break;
@@ -2392,8 +2396,7 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
repaint_func->id = context->last_repaint_id++;
/* mask out QUEUE_REDRAW_ON_ADD, since we're going to consume it */
repaint_func->flags = flags & ~CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD;
repaint_func->flags = flags;
repaint_func->func = func;
repaint_func->data = data;
repaint_func->notify = notify;
@@ -2403,13 +2406,6 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
_clutter_context_unlock ();
if ((flags & CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD) != 0)
{
ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
_clutter_master_clock_ensure_next_iteration (master_clock);
}
return repaint_func->id;
}

View File

@@ -75,7 +75,7 @@ CLUTTER_EXPORT
void clutter_stage_thaw_updates (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_update_resource_scales (ClutterStage *stage);
void clutter_stage_clear_stage_views (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_view_assign_next_scanout (ClutterStageView *stage_view,

View File

@@ -136,7 +136,8 @@ enum
static guint pan_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE_WITH_PRIVATE (ClutterPanAction, clutter_pan_action, CLUTTER_TYPE_GESTURE_ACTION)
G_DEFINE_TYPE_WITH_PRIVATE (ClutterPanAction, clutter_pan_action,
CLUTTER_TYPE_GESTURE_ACTION)
static void
emit_pan (ClutterPanAction *self,
@@ -156,14 +157,18 @@ emit_pan (ClutterPanAction *self,
gfloat scroll_threshold = G_PI_4/2;
gfloat drag_angle;
clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (self), 0, &delta_x, &delta_y);
clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (self),
0,
&delta_x,
&delta_y);
if (delta_x != 0.0f)
drag_angle = atanf (delta_y / delta_x);
else
drag_angle = G_PI_2;
if ((drag_angle > -scroll_threshold) && (drag_angle < scroll_threshold))
if ((drag_angle > -scroll_threshold) &&
(drag_angle < scroll_threshold))
priv->pin_state = SCROLL_PINNED_HORIZONTAL;
else if ((drag_angle > (G_PI_2 - scroll_threshold)) ||
(drag_angle < -(G_PI_2 - scroll_threshold)))
@@ -282,7 +287,10 @@ gesture_end (ClutterGestureAction *gesture,
gfloat tau;
gint duration;
clutter_gesture_action_get_release_coords (CLUTTER_GESTURE_ACTION (self), 0, &priv->release_x, &priv->release_y);
clutter_gesture_action_get_release_coords (CLUTTER_GESTURE_ACTION (self),
0,
&priv->release_x,
&priv->release_y);
if (!priv->should_interpolate)
{
@@ -293,7 +301,9 @@ gesture_end (ClutterGestureAction *gesture,
priv->state = PAN_STATE_INTERPOLATING;
clutter_gesture_action_get_motion_delta (gesture, 0, &delta_x, &delta_y);
velocity = clutter_gesture_action_get_velocity (gesture, 0, &velocity_x, &velocity_y);
velocity = clutter_gesture_action_get_velocity (gesture, 0,
&velocity_x,
&velocity_y);
/* Exponential timing constant v(t) = v(0) * exp(-t/tau)
* tau = 1000ms / (frame_per_second * - ln(decay_per_frame))
@@ -304,17 +314,22 @@ gesture_end (ClutterGestureAction *gesture,
/* See where the decreasing velocity reaches $min_velocity px/ms
* v(t) = v(0) * exp(-t/tau) = min_velocity
* t = - tau * ln( min_velocity / |v(0)|) */
duration = - tau * logf (min_velocity / (ABS (velocity) * priv->acceleration_factor));
duration = - tau * logf (min_velocity / (ABS (velocity) *
priv->acceleration_factor));
/* Target point: x(t) = v(0) * tau * [1 - exp(-t/tau)] */
priv->target_x = velocity_x * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau));
priv->target_y = velocity_y * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau));
priv->target_x = (velocity_x * priv->acceleration_factor * tau *
(1 - exp ((float)-duration / tau)));
priv->target_y = (velocity_y * priv->acceleration_factor * tau *
(1 - exp ((float)-duration / tau)));
if (ABS (velocity) * priv->acceleration_factor > min_velocity && duration > FLOAT_EPSILON)
if (ABS (velocity) * priv->acceleration_factor > min_velocity &&
duration > FLOAT_EPSILON)
{
priv->interpolated_x = priv->interpolated_y = 0.0f;
priv->deceleration_timeline = clutter_timeline_new (duration);
clutter_timeline_set_progress_mode (priv->deceleration_timeline, CLUTTER_EASE_OUT_EXPO);
clutter_timeline_set_progress_mode (priv->deceleration_timeline,
CLUTTER_EASE_OUT_EXPO);
g_signal_connect (priv->deceleration_timeline, "new_frame",
G_CALLBACK (on_deceleration_new_frame), self);
@@ -367,7 +382,8 @@ clutter_pan_action_set_property (GObject *gobject,
break;
case PROP_ACCELERATION_FACTOR :
clutter_pan_action_set_acceleration_factor (self, g_value_get_double (value));
clutter_pan_action_set_acceleration_factor (self,
g_value_get_double (value));
break;
default:
@@ -411,9 +427,11 @@ static void
clutter_pan_action_constructed (GObject *gobject)
{
ClutterGestureAction *gesture;
ClutterGestureTriggerEdge edge;
gesture = CLUTTER_GESTURE_ACTION (gobject);
clutter_gesture_action_set_threshold_trigger_edge (gesture, CLUTTER_GESTURE_TRIGGER_EDGE_AFTER);
edge = CLUTTER_GESTURE_TRIGGER_EDGE_AFTER;
clutter_gesture_action_set_threshold_trigger_edge (gesture, edge);
}
static void
@@ -442,7 +460,8 @@ clutter_pan_action_set_actor (ClutterActorMeta *meta,
g_clear_object (&priv->deceleration_timeline);
}
CLUTTER_ACTOR_META_CLASS (clutter_pan_action_parent_class)->set_actor (meta, actor);
CLUTTER_ACTOR_META_CLASS (clutter_pan_action_parent_class)->set_actor (meta,
actor);
}
@@ -880,7 +899,9 @@ clutter_pan_action_get_constrained_motion_delta (ClutterPanAction *self,
priv = self->priv;
distance = clutter_pan_action_get_motion_delta (self, point, &delta_x, &delta_y);
distance = clutter_pan_action_get_motion_delta (self, point,
&delta_x,
&delta_y);
switch (priv->pan_axis)
{

View File

@@ -1523,7 +1523,7 @@ clutter_script_construct_parameters (ClutterScript *script,
continue;
}
if (!(pspec->flags & G_PARAM_CONSTRUCT_ONLY))
if (!(pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)))
{
unparsed = g_list_prepend (unparsed, pinfo);
continue;

View File

@@ -354,6 +354,17 @@ clutter_seat_get_keyboard (ClutterSeat *seat)
return CLUTTER_SEAT_GET_CLASS (seat)->get_keyboard (seat);
}
/**
* clutter_seat_peek_devices: (skip)
**/
const GList *
clutter_seat_peek_devices (ClutterSeat *seat)
{
g_return_val_if_fail (CLUTTER_IS_SEAT (seat), NULL);
return CLUTTER_SEAT_GET_CLASS (seat)->peek_devices (seat);
}
/**
* clutter_seat_list_devices:
* @seat: a #ClutterSeat
@@ -370,7 +381,7 @@ clutter_seat_list_devices (ClutterSeat *seat)
{
g_return_val_if_fail (CLUTTER_IS_SEAT (seat), NULL);
return CLUTTER_SEAT_GET_CLASS (seat)->list_devices (seat);
return g_list_copy ((GList *)clutter_seat_peek_devices (seat));
}
void
@@ -634,8 +645,8 @@ clutter_seat_create_virtual_device (ClutterSeat *seat,
}
/**
* clutter_seat_supported_virtual_device_types: (skip)
*/
* clutter_seat_get_supported_virtual_device_types: (skip)
**/
ClutterVirtualDeviceType
clutter_seat_get_supported_virtual_device_types (ClutterSeat *seat)
{

View File

@@ -96,7 +96,7 @@ struct _ClutterSeatClass
ClutterInputDevice * (* get_pointer) (ClutterSeat *seat);
ClutterInputDevice * (* get_keyboard) (ClutterSeat *seat);
GList * (* list_devices) (ClutterSeat *seat);
const GList * (* peek_devices) (ClutterSeat *seat);
void (* bell_notify) (ClutterSeat *seat);
@@ -133,6 +133,7 @@ CLUTTER_EXPORT
ClutterInputDevice * clutter_seat_get_keyboard (ClutterSeat *seat);
CLUTTER_EXPORT
GList * clutter_seat_list_devices (ClutterSeat *seat);
const GList * clutter_seat_peek_devices (ClutterSeat *seat);
CLUTTER_EXPORT
void clutter_seat_bell_notify (ClutterSeat *seat);

View File

@@ -125,9 +125,6 @@ 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);
void _clutter_stage_presented (ClutterStage *stage,
CoglFrameEvent frame_event,
@@ -136,6 +133,9 @@ void _clutter_stage_presented (ClutterStage *stag
void clutter_stage_queue_actor_relayout (ClutterStage *stage,
ClutterActor *actor);
GList * clutter_stage_get_views_for_rect (ClutterStage *stage,
const graphene_rect_t *rect);
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */

View File

@@ -45,7 +45,7 @@
#include "clutter-build-config.h"
#include <math.h>
#include <cairo.h>
#include <cairo-gobject.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#define CLUTTER_ENABLE_EXPERIMENTAL_API
@@ -119,8 +119,7 @@ struct _ClutterStagePrivate
ClutterPlane current_clip_planes[4];
GHashTable *pending_relayouts;
unsigned int pending_relayouts_version;
GSList *pending_relayouts;
GList *pending_queue_redraws;
gint sync_delay;
@@ -1071,6 +1070,7 @@ clutter_stage_hide (ClutterActor *self)
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
g_assert (priv->impl != NULL);
_clutter_stage_clear_pick_stack (CLUTTER_STAGE (self));
_clutter_stage_window_hide (priv->impl);
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->hide (self);
@@ -1129,7 +1129,6 @@ _clutter_stage_queue_event (ClutterStage *stage,
event->type != CLUTTER_PROXIMITY_IN &&
event->type != CLUTTER_PROXIMITY_OUT)
{
ClutterModifierType event_state = clutter_event_get_state (event);
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
guint32 event_time = clutter_event_get_time (event);
gfloat event_x, event_y;
@@ -1137,7 +1136,6 @@ _clutter_stage_queue_event (ClutterStage *stage,
clutter_event_get_coords (event, &event_x, &event_y);
_clutter_input_device_set_coords (device, sequence, event_x, event_y, stage);
_clutter_input_device_set_state (device, event_state);
_clutter_input_device_set_time (device, event_time);
}
@@ -1294,7 +1292,7 @@ _clutter_stage_needs_update (ClutterStage *stage)
return (priv->redraw_pending ||
priv->needs_update ||
g_hash_table_size (priv->pending_relayouts) > 0);
priv->pending_relayouts != NULL);
}
void
@@ -1303,11 +1301,11 @@ clutter_stage_queue_actor_relayout (ClutterStage *stage,
{
ClutterStagePrivate *priv = stage->priv;
if (g_hash_table_size (priv->pending_relayouts) == 0)
if (priv->pending_relayouts == NULL)
clutter_stage_schedule_update (stage);
g_hash_table_add (priv->pending_relayouts, g_object_ref (actor));
priv->pending_relayouts_version++;
priv->pending_relayouts = g_slist_prepend (priv->pending_relayouts,
g_object_ref (actor));
}
void
@@ -1315,24 +1313,20 @@ _clutter_stage_maybe_relayout (ClutterActor *actor)
{
ClutterStage *stage = CLUTTER_STAGE (actor);
ClutterStagePrivate *priv = stage->priv;
GHashTableIter iter;
gpointer key;
g_autoptr (GSList) stolen_list = NULL;
GSList *l;
int count = 0;
/* No work to do? Avoid the extraneous debug log messages too. */
if (g_hash_table_size (priv->pending_relayouts) == 0)
if (priv->pending_relayouts == NULL)
return;
CLUTTER_NOTE (ACTOR, ">>> Recomputing layout");
g_hash_table_iter_init (&iter, priv->pending_relayouts);
while (g_hash_table_iter_next (&iter, &key, NULL))
stolen_list = g_steal_pointer (&priv->pending_relayouts);
for (l = stolen_list; l; l = l->next)
{
g_autoptr (ClutterActor) queued_actor = key;
unsigned int old_version;
g_hash_table_iter_steal (&iter);
priv->pending_relayouts_version++;
g_autoptr (ClutterActor) queued_actor = l->data;
if (CLUTTER_ACTOR_IN_RELAYOUT (queued_actor)) /* avoid reentrancy */
continue;
@@ -1350,16 +1344,11 @@ _clutter_stage_maybe_relayout (ClutterActor *actor)
CLUTTER_SET_PRIVATE_FLAGS (queued_actor, CLUTTER_IN_RELAYOUT);
old_version = priv->pending_relayouts_version;
clutter_actor_allocate_preferred_size (queued_actor);
CLUTTER_UNSET_PRIVATE_FLAGS (queued_actor, CLUTTER_IN_RELAYOUT);
count++;
/* Prevent using an iterator that's been invalidated */
if (old_version != priv->pending_relayouts_version)
g_hash_table_iter_init (&iter, priv->pending_relayouts);
}
CLUTTER_NOTE (ACTOR, "<<< Completed recomputing layout of %d subtrees", count);
@@ -1418,12 +1407,12 @@ _clutter_stage_check_updated_pointers (ClutterStage *stage)
ClutterBackend *backend;
ClutterSeat *seat;
GSList *updating = NULL;
GList *l, *devices;
const GList *l, *devices;
graphene_point_t point;
backend = clutter_get_default_backend ();
seat = clutter_backend_get_default_seat (backend);
devices = clutter_seat_list_devices (seat);
devices = clutter_seat_peek_devices (seat);
for (l = devices; l; l = l->next)
{
@@ -1463,11 +1452,17 @@ _clutter_stage_check_updated_pointers (ClutterStage *stage)
}
}
g_list_free (devices);
return updating;
}
static void
update_actor_stage_views (ClutterStage *stage)
{
ClutterActor *actor = CLUTTER_ACTOR (stage);
clutter_actor_update_stage_views (actor);
}
/**
* _clutter_stage_do_update:
* @stage: A #ClutterStage
@@ -1515,6 +1510,10 @@ _clutter_stage_do_update (ClutterStage *stage)
if (stage_was_relayout)
pointers = _clutter_stage_check_updated_pointers (stage);
COGL_TRACE_BEGIN (ClutterStageUpdateActorStageViews, "Actor stage-views");
update_actor_stage_views (stage);
COGL_TRACE_END (ClutterStageUpdateActorStageViews);
COGL_TRACE_BEGIN (ClutterStagePaint, "Paint");
clutter_stage_maybe_finish_queue_redraws (stage);
@@ -1910,7 +1909,9 @@ clutter_stage_dispose (GObject *object)
(GDestroyNotify) free_queue_redraw_entry);
priv->pending_queue_redraws = NULL;
g_clear_pointer (&priv->pending_relayouts, g_hash_table_destroy);
g_slist_free_full (priv->pending_relayouts,
(GDestroyNotify) g_object_unref);
priv->pending_relayouts = NULL;
/* this will release the reference on the stage */
stage_manager = clutter_stage_manager_get_default ();
@@ -2147,7 +2148,7 @@ clutter_stage_class_init (ClutterStageClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 2,
CLUTTER_TYPE_STAGE_VIEW,
G_TYPE_POINTER);
CAIRO_GOBJECT_TYPE_REGION);
/**
* ClutterStage::presented: (skip)
@@ -2224,10 +2225,6 @@ clutter_stage_init (ClutterStage *self)
clutter_actor_set_background_color (CLUTTER_ACTOR (self),
&default_stage_color);
priv->pending_relayouts = g_hash_table_new_full (NULL,
NULL,
g_object_unref,
NULL);
clutter_stage_queue_actor_relayout (self, CLUTTER_ACTOR (self));
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
@@ -3171,37 +3168,6 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
#undef _DEG_TO_RAD
/**
* clutter_stage_ensure_redraw:
* @stage: a #ClutterStage
*
* Ensures that @stage is redrawn
*
* This function should not be called by applications: it is
* used when embedding a #ClutterStage into a toolkit with
* another windowing system, like GTK+.
*
* Since: 1.0
*/
void
clutter_stage_ensure_redraw (ClutterStage *stage)
{
ClutterMasterClock *master_clock;
ClutterStagePrivate *priv;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
priv = stage->priv;
if (!_clutter_stage_needs_update (stage))
clutter_stage_schedule_update (stage);
priv->redraw_pending = TRUE;
master_clock = _clutter_master_clock_get_default ();
_clutter_master_clock_start_running (master_clock);
}
/**
* clutter_stage_is_redraw_queued: (skip)
*/
@@ -4107,20 +4073,29 @@ clutter_stage_get_capture_final_size (ClutterStage *stage,
int *out_height,
float *out_scale)
{
float max_scale;
float max_scale = 1.0;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
if (rect)
{
graphene_rect_t capture_rect;
g_autoptr (GList) views = NULL;
GList *l;
_clutter_util_rect_from_rectangle (rect, &capture_rect);
if (!_clutter_stage_get_max_view_scale_factor_for_rect (stage,
&capture_rect,
&max_scale))
views = clutter_stage_get_views_for_rect (stage, &capture_rect);
if (!views)
return FALSE;
for (l = views; l; l = l->next)
{
ClutterStageView *view = l->data;
max_scale = MAX (clutter_stage_view_get_scale (view), max_scale);
}
if (out_width)
*out_width = (gint) roundf (rect->width * max_scale);
@@ -4201,8 +4176,8 @@ clutter_stage_paint_to_buffer (ClutterStage *stage,
CoglFramebuffer *framebuffer;
CoglBitmap *bitmap;
texture_width = (int) ceilf (rect->width * scale);
texture_height = (int) ceilf (rect->height * scale);
texture_width = (int) roundf (rect->width * scale);
texture_height = (int) roundf (rect->height * scale);
texture = cogl_texture_2d_new_with_size (cogl_context,
texture_width,
texture_height);
@@ -4401,18 +4376,17 @@ clutter_stage_peek_stage_views (ClutterStage *stage)
}
void
clutter_stage_update_resource_scales (ClutterStage *stage)
clutter_stage_clear_stage_views (ClutterStage *stage)
{
_clutter_actor_queue_update_resource_scale_recursive (CLUTTER_ACTOR (stage));
clutter_actor_clear_stage_views_recursive (CLUTTER_ACTOR (stage));
}
gboolean
_clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
graphene_rect_t *rect,
float *view_scale)
GList *
clutter_stage_get_views_for_rect (ClutterStage *stage,
const graphene_rect_t *rect)
{
ClutterStagePrivate *priv = stage->priv;
float scale = 0.0f;
GList *views_for_rect = NULL;
GList *l;
for (l = _clutter_stage_window_get_views (priv->impl); l; l = l->next)
@@ -4425,12 +4399,8 @@ _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
_clutter_util_rect_from_rectangle (&view_layout, &view_rect);
if (graphene_rect_intersection (&view_rect, rect, NULL))
scale = MAX (clutter_stage_view_get_scale (view), scale);
views_for_rect = g_list_prepend (views_for_rect, view);
}
if (scale == 0.0)
return FALSE;
*view_scale = scale;
return TRUE;
return views_for_rect;
}

View File

@@ -195,8 +195,6 @@ guchar * clutter_stage_read_pixels (ClutterStage
CLUTTER_EXPORT
void clutter_stage_ensure_viewport (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_ensure_redraw (ClutterStage *stage);
CLUTTER_EXPORT
gboolean clutter_stage_is_redraw_queued (ClutterStage *stage);

View File

@@ -172,7 +172,6 @@ enum
{
PROP_0,
PROP_LOOP,
PROP_DELAY,
PROP_DURATION,
PROP_DIRECTION,
@@ -290,23 +289,6 @@ clutter_timeline_add_marker_internal (ClutterTimeline *timeline,
g_hash_table_insert (priv->markers_by_name, marker->name, marker);
}
static inline void
clutter_timeline_set_loop_internal (ClutterTimeline *timeline,
gboolean loop)
{
gint old_repeat_count;
old_repeat_count = timeline->priv->repeat_count;
if (loop)
clutter_timeline_set_repeat_count (timeline, -1);
else
clutter_timeline_set_repeat_count (timeline, 0);
if (old_repeat_count != timeline->priv->repeat_count)
g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_LOOP]);
}
/* Scriptable */
typedef struct _ParseClosure {
ClutterTimeline *timeline;
@@ -448,10 +430,6 @@ clutter_timeline_set_property (GObject *object,
switch (prop_id)
{
case PROP_LOOP:
clutter_timeline_set_loop_internal (timeline, g_value_get_boolean (value));
break;
case PROP_DELAY:
clutter_timeline_set_delay (timeline, g_value_get_uint (value));
break;
@@ -493,10 +471,6 @@ clutter_timeline_get_property (GObject *object,
switch (prop_id)
{
case PROP_LOOP:
g_value_set_boolean (value, priv->repeat_count != 0);
break;
case PROP_DELAY:
g_value_set_uint (value, priv->delay);
break;
@@ -572,25 +546,6 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
/**
* ClutterTimeline:loop:
*
* Whether the timeline should automatically rewind and restart.
*
* As a side effect, setting this property to %TRUE will set the
* #ClutterTimeline:repeat-count property to -1, while setting this
* property to %FALSE will set the #ClutterTimeline:repeat-count
* property to 0.
*
* Deprecated: 1.10: Use the #ClutterTimeline:repeat-count property instead.
*/
obj_props[PROP_LOOP] =
g_param_spec_boolean ("loop",
P_("Loop"),
P_("Should the timeline automatically restart"),
FALSE,
CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
/**
* ClutterTimeline:delay:
*
@@ -1251,45 +1206,6 @@ clutter_timeline_stop (ClutterTimeline *timeline)
g_signal_emit (timeline, timeline_signals[STOPPED], 0, FALSE);
}
/**
* clutter_timeline_set_loop:
* @timeline: a #ClutterTimeline
* @loop: %TRUE for enable looping
*
* Sets whether @timeline should loop.
*
* This function is equivalent to calling clutter_timeline_set_repeat_count()
* with -1 if @loop is %TRUE, and with 0 if @loop is %FALSE.
*
* Deprecated: 1.10: Use clutter_timeline_set_repeat_count() instead.
*/
void
clutter_timeline_set_loop (ClutterTimeline *timeline,
gboolean loop)
{
g_return_if_fail (CLUTTER_IS_TIMELINE (timeline));
clutter_timeline_set_loop_internal (timeline, loop);
}
/**
* clutter_timeline_get_loop:
* @timeline: a #ClutterTimeline
*
* Gets whether @timeline is looping
*
* Return value: %TRUE if the timeline is looping
*
* Deprecated: 1.10: Use clutter_timeline_get_repeat_count() instead.
*/
gboolean
clutter_timeline_get_loop (ClutterTimeline *timeline)
{
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE);
return timeline->priv->repeat_count != 0;
}
/**
* clutter_timeline_rewind:
* @timeline: A #ClutterTimeline
@@ -1405,49 +1321,11 @@ clutter_timeline_is_playing (ClutterTimeline *timeline)
return timeline->priv->is_playing;
}
/**
* clutter_timeline_clone:
* @timeline: #ClutterTimeline to duplicate.
*
* Create a new #ClutterTimeline instance which has property values
* matching that of supplied timeline. The cloned timeline will not
* be started and will not be positioned to the current position of
* the original @timeline: you will have to start it with
* clutter_timeline_start().
*
* The only cloned properties are:
*
* - #ClutterTimeline:duration
* - #ClutterTimeline:loop
* - #ClutterTimeline:delay
* - #ClutterTimeline:direction
*
* Return value: (transfer full): a new #ClutterTimeline, cloned
* from @timeline
*
* Since: 0.4
*
* Deprecated: 1.10: Use clutter_timeline_new() or g_object_new()
* instead
*/
ClutterTimeline *
clutter_timeline_clone (ClutterTimeline *timeline)
{
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL);
return g_object_new (CLUTTER_TYPE_TIMELINE,
"duration", timeline->priv->duration,
"loop", timeline->priv->repeat_count != 0,
"delay", timeline->priv->delay,
"direction", timeline->priv->direction,
NULL);
}
/**
* clutter_timeline_new:
* @msecs: Duration of the timeline in milliseconds
* @duration_ms: Duration of the timeline in milliseconds
*
* Creates a new #ClutterTimeline with a duration of @msecs.
* Creates a new #ClutterTimeline with a duration of @duration_ms milli seconds.
*
* Return value: the newly created #ClutterTimeline instance. Use
* g_object_unref() when done using it
@@ -1455,10 +1333,10 @@ clutter_timeline_clone (ClutterTimeline *timeline)
* Since: 0.6
*/
ClutterTimeline *
clutter_timeline_new (guint msecs)
clutter_timeline_new (guint duration_ms)
{
return g_object_new (CLUTTER_TYPE_TIMELINE,
"duration", msecs,
"duration", duration_ms,
NULL);
}

View File

@@ -119,7 +119,7 @@ CLUTTER_EXPORT
GType clutter_timeline_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterTimeline * clutter_timeline_new (guint msecs);
ClutterTimeline * clutter_timeline_new (guint duration_ms);
CLUTTER_EXPORT
guint clutter_timeline_get_duration (ClutterTimeline *timeline);

View File

@@ -174,6 +174,20 @@ struct _ClutterActorBox
*/
#define CLUTTER_ACTOR_BOX_INIT_ZERO CLUTTER_ACTOR_BOX_INIT (0.f, 0.f, 0.f, 0.f)
/**
* CLUTTER_ACTOR_BOX_UNINITIALIZED:
*
* A simple macro for creating a #ClutterActorBox with a size of -1 when
* declaring it, e.g.:
*
* |[
* ClutterActorBox box = CLUTTER_ACTOR_BOX_UNINITIALIZED;
* ]|
*/
#define CLUTTER_ACTOR_BOX_UNINITIALIZED { .x1 = INFINITY, .y1 = INFINITY, .x2 = -INFINITY, .y2 = -INFINITY }
CLUTTER_EXPORT
GType clutter_actor_box_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
@@ -252,6 +266,9 @@ CLUTTER_EXPORT
void clutter_actor_box_scale (ClutterActorBox *box,
gfloat scale);
CLUTTER_EXPORT
gboolean clutter_actor_box_is_initialized (ClutterActorBox *box);
/**
* ClutterKnot:
* @x: X coordinate of the knot

View File

@@ -551,7 +551,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view);
cairo_rectangle_int_t view_rect;
gboolean is_full_redraw;
gboolean use_clipped_redraw;
gboolean use_clipped_redraw = TRUE;
gboolean can_blit_sub_buffer;
gboolean has_buffer_age;
gboolean swap_with_damage;
@@ -561,7 +561,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
cairo_region_t *swap_region;
float fb_scale;
int fb_width, fb_height;
int buffer_age;
int buffer_age = 0;
gboolean res;
clutter_stage_view_get_layout (view, &view_rect);

View File

@@ -26,16 +26,6 @@
G_BEGIN_DECLS
CLUTTER_DEPRECATED_FOR(clutter_timeline_new)
ClutterTimeline * clutter_timeline_clone (ClutterTimeline *timeline);
CLUTTER_DEPRECATED_FOR(clutter_timeline_set_repeat_count)
void clutter_timeline_set_loop (ClutterTimeline *timeline,
gboolean loop);
CLUTTER_DEPRECATED_FOR(clutter_timeline_get_repeat_count)
gboolean clutter_timeline_get_loop (ClutterTimeline *timeline);
G_END_DECLS
#endif /* __CLUTTER_TIMELINE_PRIVATE_H__ */

View File

@@ -48,7 +48,6 @@
#include "cogl1-context.h"
#include "cogl-sub-texture.h"
#include "cogl-gtype-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include "driver/gl/cogl-texture-gl-private.h"
#include <stdlib.h>

View File

@@ -51,11 +51,6 @@
#include <stdio.h>
#include <stdlib.h>
/* This isn't defined in the GLES headers */
#ifndef GL_UNSIGNED_INT
#define GL_UNSIGNED_INT 0x1405
#endif
static void _cogl_attribute_free (CoglAttribute *attribute);
COGL_OBJECT_DEFINE (Attribute, attribute);

View File

@@ -34,7 +34,6 @@
#include "cogl-boxed-value.h"
#include "cogl-context-private.h"
#include "driver/gl/cogl-util-gl-private.h"
gboolean
_cogl_boxed_value_equal (const CoglBoxedValue *bva,
@@ -286,90 +285,5 @@ _cogl_boxed_value_set_uniform (CoglContext *ctx,
GLint location,
const CoglBoxedValue *value)
{
switch (value->type)
{
case COGL_BOXED_NONE:
break;
case COGL_BOXED_INT:
{
const int *ptr;
if (value->count == 1)
ptr = value->v.int_value;
else
ptr = value->v.int_array;
switch (value->size)
{
case 1:
GE( ctx, glUniform1iv (location, value->count, ptr) );
break;
case 2:
GE( ctx, glUniform2iv (location, value->count, ptr) );
break;
case 3:
GE( ctx, glUniform3iv (location, value->count, ptr) );
break;
case 4:
GE( ctx, glUniform4iv (location, value->count, ptr) );
break;
}
}
break;
case COGL_BOXED_FLOAT:
{
const float *ptr;
if (value->count == 1)
ptr = value->v.float_value;
else
ptr = value->v.float_array;
switch (value->size)
{
case 1:
GE( ctx, glUniform1fv (location, value->count, ptr) );
break;
case 2:
GE( ctx, glUniform2fv (location, value->count, ptr) );
break;
case 3:
GE( ctx, glUniform3fv (location, value->count, ptr) );
break;
case 4:
GE( ctx, glUniform4fv (location, value->count, ptr) );
break;
}
}
break;
case COGL_BOXED_MATRIX:
{
const float *ptr;
if (value->count == 1)
ptr = value->v.matrix;
else
ptr = value->v.float_array;
switch (value->size)
{
case 2:
GE( ctx, glUniformMatrix2fv (location, value->count,
FALSE, ptr) );
break;
case 3:
GE( ctx, glUniformMatrix3fv (location, value->count,
FALSE, ptr) );
break;
case 4:
GE( ctx, glUniformMatrix4fv (location, value->count,
FALSE, ptr) );
break;
}
}
break;
}
ctx->driver_vtable->set_uniform (ctx, location, value);
}

View File

@@ -46,7 +46,6 @@
#include "cogl-pipeline-cache.h"
#include "cogl-texture-2d.h"
#include "cogl-sampler-cache-private.h"
#include "cogl-gpu-info-private.h"
#include "cogl-gl-header.h"
#include "cogl-framebuffer-private.h"
#include "cogl-onscreen-private.h"
@@ -70,14 +69,12 @@ struct _CoglContext
CoglDriver driver;
/* Information about the GPU and driver which we can use to
determine certain workarounds */
CoglGpuInfo gpu;
/* vtables for the driver functions */
const CoglDriverVtable *driver_vtable;
const CoglTextureDriver *texture_driver;
void *driver_context;
int glsl_major;
int glsl_minor;
@@ -124,9 +121,6 @@ struct _CoglContext
CoglMatrixEntry identity_entry;
GArray *texture_units;
int active_texture_unit;
/* Only used for comparing other pipelines when reading pixels. */
CoglPipeline *opaque_color_pipeline;
@@ -315,18 +309,4 @@ void
_cogl_context_set_current_modelview_entry (CoglContext *context,
CoglMatrixEntry *entry);
/*
* _cogl_context_get_gl_extensions:
* @context: A CoglContext
*
* Return value: a NULL-terminated array of strings representing the
* supported extensions by the current driver. This array is owned
* by the caller and should be freed with g_strfreev().
*/
char **
_cogl_context_get_gl_extensions (CoglContext *context);
const char *
_cogl_context_get_gl_version (CoglContext *context);
#endif /* __COGL_CONTEXT_PRIVATE_H */

View File

@@ -45,40 +45,12 @@
#include "cogl-onscreen-private.h"
#include "cogl-attribute-private.h"
#include "cogl1-context.h"
#include "cogl-gpu-info-private.h"
#include "cogl-gtype-private.h"
#include "winsys/cogl-winsys-private.h"
#include <string.h>
#include <stdlib.h>
/* These aren't defined in the GLES headers */
#ifndef GL_POINT_SPRITE
#define GL_POINT_SPRITE 0x8861
#endif
#ifndef GL_NUM_EXTENSIONS
#define GL_NUM_EXTENSIONS 0x821D
#endif
/* This is a relatively new extension */
#ifndef GL_PURGED_CONTEXT_RESET_NV
#define GL_PURGED_CONTEXT_RESET_NV 0x92BB
#endif
/* These aren't defined in the GLES2 headers */
#ifndef GL_GUILTY_CONTEXT_RESET_ARB
#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
#endif
#ifndef GL_INNOCENT_CONTEXT_RESET_ARB
#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
#endif
#ifndef GL_UNKNOWN_CONTEXT_RESET_ARB
#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
#endif
static void _cogl_context_free (CoglContext *context);
COGL_OBJECT_DEFINE (Context, context);
@@ -470,94 +442,6 @@ _cogl_context_set_current_modelview_entry (CoglContext *context,
context->current_modelview_entry = entry;
}
char **
_cogl_context_get_gl_extensions (CoglContext *context)
{
const char *env_disabled_extensions;
char **ret;
/* In GL 3, querying GL_EXTENSIONS is deprecated so we have to build
* the array using glGetStringi instead */
#ifdef HAVE_COGL_GL
if (context->driver == COGL_DRIVER_GL3)
{
int num_extensions, i;
context->glGetIntegerv (GL_NUM_EXTENSIONS, &num_extensions);
ret = g_malloc (sizeof (char *) * (num_extensions + 1));
for (i = 0; i < num_extensions; i++)
{
const char *ext =
(const char *) context->glGetStringi (GL_EXTENSIONS, i);
ret[i] = g_strdup (ext);
}
ret[num_extensions] = NULL;
}
else
#endif
{
const char *all_extensions =
(const char *) context->glGetString (GL_EXTENSIONS);
ret = g_strsplit (all_extensions, " ", 0 /* max tokens */);
}
if ((env_disabled_extensions = g_getenv ("COGL_DISABLE_GL_EXTENSIONS")))
{
char **split_env_disabled_extensions;
char **src, **dst;
if (env_disabled_extensions)
split_env_disabled_extensions =
g_strsplit (env_disabled_extensions,
",",
0 /* no max tokens */);
else
split_env_disabled_extensions = NULL;
for (dst = ret, src = ret;
*src;
src++)
{
char **d;
if (split_env_disabled_extensions)
for (d = split_env_disabled_extensions; *d; d++)
if (!strcmp (*src, *d))
goto disabled;
*(dst++) = *src;
continue;
disabled:
g_free (*src);
continue;
}
*dst = NULL;
if (split_env_disabled_extensions)
g_strfreev (split_env_disabled_extensions);
}
return ret;
}
const char *
_cogl_context_get_gl_version (CoglContext *context)
{
const char *version_override;
if ((version_override = g_getenv ("COGL_OVERRIDE_GL_VERSION")))
return version_override;
else
return (const char *) context->glGetString (GL_VERSION);
}
int64_t
cogl_get_clock_time (CoglContext *context)
{
@@ -572,24 +456,11 @@ cogl_get_clock_time (CoglContext *context)
CoglGraphicsResetStatus
cogl_get_graphics_reset_status (CoglContext *context)
{
if (!context->glGetGraphicsResetStatus)
return COGL_GRAPHICS_RESET_STATUS_NO_ERROR;
switch (context->glGetGraphicsResetStatus ())
{
case GL_GUILTY_CONTEXT_RESET_ARB:
return COGL_GRAPHICS_RESET_STATUS_GUILTY_CONTEXT_RESET;
case GL_INNOCENT_CONTEXT_RESET_ARB:
return COGL_GRAPHICS_RESET_STATUS_INNOCENT_CONTEXT_RESET;
case GL_UNKNOWN_CONTEXT_RESET_ARB:
return COGL_GRAPHICS_RESET_STATUS_UNKNOWN_CONTEXT_RESET;
case GL_PURGED_CONTEXT_RESET_NV:
return COGL_GRAPHICS_RESET_STATUS_PURGED_CONTEXT_RESET;
default:
return COGL_GRAPHICS_RESET_STATUS_NO_ERROR;
}
return context->driver_vtable->get_graphics_reset_status (context);
}
gboolean
cogl_context_is_hardware_accelerated (CoglContext *context)
{
return context->driver_vtable->is_hardware_accelerated (context);
}

View File

@@ -357,6 +357,16 @@ typedef enum _CoglGraphicsResetStatus
COGL_EXPORT CoglGraphicsResetStatus
cogl_get_graphics_reset_status (CoglContext *context);
/**
* cogl_context_is_hardware_accelerated:
* @context: a #CoglContext pointer
*
* Returns: %TRUE if the @context is hardware accelerated, or %FALSE if
* not.
*/
COGL_EXPORT gboolean
cogl_context_is_hardware_accelerated (CoglContext *context);
G_END_DECLS
#endif /* __COGL_CONTEXT_H__ */

View File

@@ -35,6 +35,7 @@
#include "cogl-offscreen.h"
#include "cogl-framebuffer-private.h"
#include "cogl-attribute-private.h"
#include "cogl-sampler-cache-private.h"
typedef struct _CoglDriverVtable CoglDriverVtable;
@@ -46,6 +47,12 @@ struct _CoglDriverVtable
void
(* context_deinit) (CoglContext *context);
gboolean
(* is_hardware_accelerated) (CoglContext *context);
CoglGraphicsResetStatus
(* get_graphics_reset_status) (CoglContext *context);
/* TODO: factor this out since this is OpenGL specific and
* so can be ignored by non-OpenGL drivers. */
gboolean
@@ -262,6 +269,19 @@ struct _CoglDriverVtable
const void *data,
unsigned int size,
GError **error);
void
(*sampler_init) (CoglContext *context,
CoglSamplerCacheEntry *entry);
void
(*sampler_free) (CoglContext *context,
CoglSamplerCacheEntry *entry);
void
(* set_uniform) (CoglContext *ctx,
GLint location,
const CoglBoxedValue *value);
};
#define COGL_DRIVER_ERROR (_cogl_driver_error_quark ())

View File

@@ -43,8 +43,6 @@ struct _CoglFrameInfo
float refresh_rate;
int64_t global_frame_counter;
CoglOutput *output;
};
CoglFrameInfo *_cogl_frame_info_new (void);

View File

@@ -72,12 +72,6 @@ cogl_frame_info_get_refresh_rate (CoglFrameInfo *info)
return info->refresh_rate;
}
CoglOutput *
cogl_frame_info_get_output (CoglFrameInfo *info)
{
return info->output;
}
int64_t
cogl_frame_info_get_global_frame_counter (CoglFrameInfo *info)
{

View File

@@ -126,20 +126,6 @@ int64_t cogl_frame_info_get_presentation_time (CoglFrameInfo *info);
COGL_EXPORT
float cogl_frame_info_get_refresh_rate (CoglFrameInfo *info);
/**
* cogl_frame_info_get_output:
* @info: a #CoglFrameInfo object
*
* Gets the #CoglOutput that the swapped frame was presented to.
*
* Return value: (transfer none): The #CoglOutput that the frame was
* presented to, or %NULL if this could not be determined.
* Since: 1.14
* Stability: unstable
*/
COGL_EXPORT CoglOutput *
cogl_frame_info_get_output (CoglFrameInfo *info);
/**
* cogl_frame_info_get_global_frame_counter: (skip)
*/

View File

@@ -1,41 +0,0 @@
/*
* Cogl
*
* A Low Level GPU Graphics and Utilities API
*
* Copyright (C) 2012 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _COGL_GLSL_SHADER_PRIVATE_H_
#define _COGL_GLSL_SHADER_PRIVATE_H_
void
_cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx,
GLuint shader_gl_handle,
GLenum shader_gl_type,
CoglPipeline *pipeline,
GLsizei count_in,
const char **strings_in,
const GLint *lengths_in);
#endif /* _COGL_GLSL_SHADER_PRIVATE_H_ */

View File

@@ -1,189 +0,0 @@
/*
* Cogl
*
* A Low Level GPU Graphics and Utilities API
*
* Copyright (C) 2012 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*
* Authors:
* Robert Bragg <robert@linux.intel.com>
* Neil Roberts <neil@linux.intel.com>
*/
#include "cogl-config.h"
#include "cogl-context-private.h"
#include "cogl-glsl-shader-private.h"
#include "cogl-glsl-shader-boilerplate.h"
#include "driver/gl/cogl-util-gl-private.h"
#include <string.h>
#include <glib.h>
static gboolean
add_layer_vertex_boilerplate_cb (CoglPipelineLayer *layer,
void *user_data)
{
GString *layer_declarations = user_data;
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
g_string_append_printf (layer_declarations,
"attribute vec4 cogl_tex_coord%d_in;\n"
"#define cogl_texture_matrix%i cogl_texture_matrix[%i]\n"
"#define cogl_tex_coord%i_out _cogl_tex_coord[%i]\n",
layer->index,
layer->index,
unit_index,
layer->index,
unit_index);
return TRUE;
}
static gboolean
add_layer_fragment_boilerplate_cb (CoglPipelineLayer *layer,
void *user_data)
{
GString *layer_declarations = user_data;
g_string_append_printf (layer_declarations,
"#define cogl_tex_coord%i_in _cogl_tex_coord[%i]\n",
layer->index,
_cogl_pipeline_layer_get_unit_index (layer));
return TRUE;
}
void
_cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx,
GLuint shader_gl_handle,
GLenum shader_gl_type,
CoglPipeline *pipeline,
GLsizei count_in,
const char **strings_in,
const GLint *lengths_in)
{
const char *vertex_boilerplate;
const char *fragment_boilerplate;
const char **strings = g_alloca (sizeof (char *) * (count_in + 4));
GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 4));
char *version_string;
int count = 0;
int n_layers;
vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE;
fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE;
version_string = g_strdup_printf ("#version %i\n\n",
ctx->glsl_version_to_use);
strings[count] = version_string;
lengths[count++] = -1;
if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL))
{
static const char image_external_extension[] =
"#extension GL_OES_EGL_image_external : require\n";
strings[count] = image_external_extension;
lengths[count++] = sizeof (image_external_extension) - 1;
}
if (shader_gl_type == GL_VERTEX_SHADER)
{
strings[count] = vertex_boilerplate;
lengths[count++] = strlen (vertex_boilerplate);
}
else if (shader_gl_type == GL_FRAGMENT_SHADER)
{
strings[count] = fragment_boilerplate;
lengths[count++] = strlen (fragment_boilerplate);
}
n_layers = cogl_pipeline_get_n_layers (pipeline);
if (n_layers)
{
GString *layer_declarations = ctx->codegen_boilerplate_buffer;
g_string_set_size (layer_declarations, 0);
g_string_append_printf (layer_declarations,
"varying vec4 _cogl_tex_coord[%d];\n",
n_layers);
if (shader_gl_type == GL_VERTEX_SHADER)
{
g_string_append_printf (layer_declarations,
"uniform mat4 cogl_texture_matrix[%d];\n",
n_layers);
_cogl_pipeline_foreach_layer_internal (pipeline,
add_layer_vertex_boilerplate_cb,
layer_declarations);
}
else if (shader_gl_type == GL_FRAGMENT_SHADER)
{
_cogl_pipeline_foreach_layer_internal (pipeline,
add_layer_fragment_boilerplate_cb,
layer_declarations);
}
strings[count] = layer_declarations->str;
lengths[count++] = -1; /* null terminated */
}
memcpy (strings + count, strings_in, sizeof (char *) * count_in);
if (lengths_in)
memcpy (lengths + count, lengths_in, sizeof (GLint) * count_in);
else
{
int i;
for (i = 0; i < count_in; i++)
lengths[count + i] = -1; /* null terminated */
}
count += count_in;
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
{
GString *buf = g_string_new (NULL);
int i;
g_string_append_printf (buf,
"%s shader:\n",
shader_gl_type == GL_VERTEX_SHADER ?
"vertex" : "fragment");
for (i = 0; i < count; i++)
if (lengths[i] != -1)
g_string_append_len (buf, strings[i], lengths[i]);
else
g_string_append (buf, strings[i]);
g_message ("%s", buf->str);
g_string_free (buf, TRUE);
}
GE( ctx, glShaderSource (shader_gl_handle, count,
(const char **) strings, lengths) );
g_free (version_string);
}

View File

@@ -1,112 +0,0 @@
/*
* Cogl
*
* A Low Level GPU Graphics and Utilities API
*
* Copyright (C) 2012 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
#ifndef __COGL_GPU_INFO_PRIVATE_H
#define __COGL_GPU_INFO_PRIVATE_H
#include "cogl-context.h"
typedef enum _CoglGpuInfoArchitectureFlag
{
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE,
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED,
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE,
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_DEFERRED,
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE
} CoglGpuInfoArchitectureFlag;
typedef enum _CoglGpuInfoArchitecture
{
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE,
COGL_GPU_INFO_ARCHITECTURE_SGX,
COGL_GPU_INFO_ARCHITECTURE_MALI,
COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE,
COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE,
COGL_GPU_INFO_ARCHITECTURE_SWRAST
} CoglGpuInfoArchitecture;
typedef enum
{
COGL_GPU_INFO_VENDOR_UNKNOWN,
COGL_GPU_INFO_VENDOR_INTEL,
COGL_GPU_INFO_VENDOR_IMAGINATION_TECHNOLOGIES,
COGL_GPU_INFO_VENDOR_ARM,
COGL_GPU_INFO_VENDOR_QUALCOMM,
COGL_GPU_INFO_VENDOR_NVIDIA,
COGL_GPU_INFO_VENDOR_ATI,
COGL_GPU_INFO_VENDOR_MESA
} CoglGpuInfoVendor;
typedef enum
{
COGL_GPU_INFO_DRIVER_PACKAGE_UNKNOWN,
COGL_GPU_INFO_DRIVER_PACKAGE_MESA
} CoglGpuInfoDriverPackage;
typedef enum
{
COGL_GPU_INFO_DRIVER_STUB
} CoglGpuInfoDriverBug;
typedef struct _CoglGpuInfoVersion CoglGpuInfoVersion;
typedef struct _CoglGpuInfo CoglGpuInfo;
struct _CoglGpuInfo
{
CoglGpuInfoVendor vendor;
const char *vendor_name;
CoglGpuInfoDriverPackage driver_package;
const char *driver_package_name;
int driver_package_version;
CoglGpuInfoArchitecture architecture;
const char *architecture_name;
CoglGpuInfoArchitectureFlag architecture_flags;
CoglGpuInfoDriverBug driver_bugs;
};
/*
* _cogl_gpu_info_init:
* @ctx: A #CoglContext
* @gpu: A return location for the GPU information
*
* Determines information about the GPU and driver from the given
* context.
*/
void
_cogl_gpu_info_init (CoglContext *ctx,
CoglGpuInfo *gpu);
#endif /* __COGL_GPU_INFO_PRIVATE_H */

View File

@@ -1,572 +0,0 @@
/*
* Cogl
*
* A Low Level GPU Graphics and Utilities API
*
* Copyright (C) 2012 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
#include "cogl-config.h"
#include <string.h>
#include <errno.h>
#include <test-fixtures/test-unit.h>
#include "cogl-gpu-info-private.h"
#include "cogl-context-private.h"
#include "cogl-version.h"
typedef struct
{
const char *renderer_string;
const char *version_string;
const char *vendor_string;
} CoglGpuInfoStrings;
typedef struct CoglGpuInfoArchitectureDescription
{
CoglGpuInfoArchitecture architecture;
const char *name;
CoglGpuInfoArchitectureFlag flags;
gboolean (* check_function) (const CoglGpuInfoStrings *strings);
} CoglGpuInfoArchitectureDescription;
typedef struct
{
CoglGpuInfoVendor vendor;
const char *name;
gboolean (* check_function) (const CoglGpuInfoStrings *strings);
const CoglGpuInfoArchitectureDescription *architectures;
} CoglGpuInfoVendorDescription;
typedef struct
{
CoglGpuInfoDriverPackage driver_package;
const char *name;
gboolean (* check_function) (const CoglGpuInfoStrings *strings,
int *version_out);
} CoglGpuInfoDriverPackageDescription;
static gboolean
_cogl_gpu_info_parse_version_string (const char *version_string,
int n_components,
const char **tail,
int *version_ret)
{
int version = 0;
uint64_t part;
int i;
for (i = 0; ; i++)
{
errno = 0;
part = g_ascii_strtoull (version_string,
(char **) &version_string,
10);
if (errno || part > COGL_VERSION_MAX_COMPONENT_VALUE)
return FALSE;
version |= part << ((2 - i) * COGL_VERSION_COMPONENT_BITS);
if (i + 1 >= n_components)
break;
if (*version_string != '.')
return FALSE;
version_string++;
}
if (version_ret)
*version_ret = version;
if (tail)
*tail = version_string;
return TRUE;
}
static gboolean
match_phrase (const char *string, const char *phrase)
{
const char *part = strstr (string, phrase);
int len;
if (part == NULL)
return FALSE;
/* The match must either be at the beginning of the string or
preceded by a space. */
if (part > string && part[-1] != ' ')
return FALSE;
/* Also match must either be at end of string or followed by a
* space. */
len = strlen (phrase);
if (part[len] != '\0' && part[len] != ' ')
return FALSE;
return TRUE;
}
static gboolean
check_intel_vendor (const CoglGpuInfoStrings *strings)
{
return match_phrase (strings->renderer_string, "Intel(R)");
}
static gboolean
check_imagination_technologies_vendor (const CoglGpuInfoStrings *strings)
{
if (strcmp (strings->vendor_string, "Imagination Technologies") != 0)
return FALSE;
return TRUE;
}
static gboolean
check_arm_vendor (const CoglGpuInfoStrings *strings)
{
if (strcmp (strings->vendor_string, "ARM") != 0)
return FALSE;
return TRUE;
}
static gboolean
check_qualcomm_vendor (const CoglGpuInfoStrings *strings)
{
if (strcmp (strings->vendor_string, "Qualcomm") != 0)
return FALSE;
return TRUE;
}
static gboolean
check_nvidia_vendor (const CoglGpuInfoStrings *strings)
{
if (strcmp (strings->vendor_string, "NVIDIA") != 0 &&
strcmp (strings->vendor_string, "NVIDIA Corporation") != 0)
return FALSE;
return TRUE;
}
static gboolean
check_ati_vendor (const CoglGpuInfoStrings *strings)
{
if (strcmp (strings->vendor_string, "ATI") != 0)
return FALSE;
return TRUE;
}
static gboolean
check_mesa_vendor (const CoglGpuInfoStrings *strings)
{
if (strcmp (strings->vendor_string, "Tungsten Graphics, Inc") == 0)
return TRUE;
else if (strcmp (strings->vendor_string, "VMware, Inc.") == 0)
return TRUE;
else if (strcmp (strings->vendor_string, "Mesa Project") == 0)
return TRUE;
return FALSE;
}
static gboolean
check_true (const CoglGpuInfoStrings *strings)
{
/* This is a last resort so it always matches */
return TRUE;
}
static gboolean
check_sandybridge_architecture (const CoglGpuInfoStrings *strings)
{
return match_phrase (strings->renderer_string, "Sandybridge");
}
static gboolean
check_llvmpipe_architecture (const CoglGpuInfoStrings *strings)
{
return match_phrase (strings->renderer_string, "llvmpipe");
}
static gboolean
check_softpipe_architecture (const CoglGpuInfoStrings *strings)
{
return match_phrase (strings->renderer_string, "softpipe");
}
static gboolean
check_swrast_architecture (const CoglGpuInfoStrings *strings)
{
return match_phrase (strings->renderer_string, "software rasterizer") ||
match_phrase (strings->renderer_string, "Software Rasterizer");
}
static gboolean
check_sgx_architecture (const CoglGpuInfoStrings *strings)
{
if (strncmp (strings->renderer_string, "PowerVR SGX", 12) != 0)
return FALSE;
return TRUE;
}
static gboolean
check_mali_architecture (const CoglGpuInfoStrings *strings)
{
if (strncmp (strings->renderer_string, "Mali-", 5) != 0)
return FALSE;
return TRUE;
}
static const CoglGpuInfoArchitectureDescription
intel_architectures[] =
{
{
COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE,
"Sandybridge",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
check_sandybridge_architecture
},
{
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
"Unknown",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
check_true
}
};
static const CoglGpuInfoArchitectureDescription
powervr_architectures[] =
{
{
COGL_GPU_INFO_ARCHITECTURE_SGX,
"SGX",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_DEFERRED,
check_sgx_architecture
},
{
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
"Unknown",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED |
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED,
check_true
}
};
static const CoglGpuInfoArchitectureDescription
arm_architectures[] =
{
{
COGL_GPU_INFO_ARCHITECTURE_MALI,
"Mali",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
check_mali_architecture
},
{
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
"Unknown",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
check_true
}
};
static const CoglGpuInfoArchitectureDescription
mesa_architectures[] =
{
{
COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE,
"LLVM Pipe",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE,
check_llvmpipe_architecture
},
{
COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE,
"Softpipe",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE,
check_softpipe_architecture
},
{
COGL_GPU_INFO_ARCHITECTURE_SWRAST,
"SWRast",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE,
check_swrast_architecture
},
{
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
"Unknown",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
check_true
}
};
static const CoglGpuInfoArchitectureDescription
unknown_architectures[] =
{
{
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
"Unknown",
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE,
check_true
}
};
static const CoglGpuInfoVendorDescription
_cogl_gpu_info_vendors[] =
{
{
COGL_GPU_INFO_VENDOR_INTEL,
"Intel",
check_intel_vendor,
intel_architectures
},
{
COGL_GPU_INFO_VENDOR_IMAGINATION_TECHNOLOGIES,
"Imagination Technologies",
check_imagination_technologies_vendor,
powervr_architectures
},
{
COGL_GPU_INFO_VENDOR_ARM,
"ARM",
check_arm_vendor,
arm_architectures
},
{
COGL_GPU_INFO_VENDOR_QUALCOMM,
"Qualcomm",
check_qualcomm_vendor,
unknown_architectures
},
{
COGL_GPU_INFO_VENDOR_NVIDIA,
"Nvidia",
check_nvidia_vendor,
unknown_architectures
},
{
COGL_GPU_INFO_VENDOR_ATI,
"ATI",
check_ati_vendor,
unknown_architectures
},
/* Must be last */
{
COGL_GPU_INFO_VENDOR_MESA,
"Mesa",
check_mesa_vendor,
mesa_architectures
},
{
COGL_GPU_INFO_VENDOR_UNKNOWN,
"Unknown",
check_true,
unknown_architectures
}
};
static gboolean
check_mesa_driver_package (const CoglGpuInfoStrings *strings,
int *version_ret)
{
uint64_t micro_part;
const char *v;
/* The version string should always begin a two-part GL version
number */
if (!_cogl_gpu_info_parse_version_string (strings->version_string,
2, /* n_components */
&v, /* tail */
NULL /* version_ret */))
return FALSE;
/* In mesa this will be followed optionally by "(Core Profile)" and
* then "Mesa" */
v = strstr (v, " Mesa ");
if (!v)
return FALSE;
v += 6;
/* Next there will be a version string that is at least two
components. On a git devel build the version will be something
like "-devel<git hash>" instead */
if (!_cogl_gpu_info_parse_version_string (v,
2, /* n_components */
&v, /* tail */
version_ret))
return FALSE;
/* If it is a development build then we'll just leave the micro
number as 0 */
if (g_str_has_prefix (v, "-devel"))
return TRUE;
/* Otherwise there should be a micro version number */
if (*v != '.')
return FALSE;
errno = 0;
micro_part = g_ascii_strtoull (v + 1, NULL /* endptr */, 10 /* base */);
if (errno || micro_part > COGL_VERSION_MAX_COMPONENT_VALUE)
return FALSE;
*version_ret = COGL_VERSION_ENCODE (COGL_VERSION_GET_MAJOR (*version_ret),
COGL_VERSION_GET_MINOR (*version_ret),
micro_part);
return TRUE;
}
UNIT_TEST (check_mesa_driver_package_parser,
0, /* no requirements */
0 /* no failure cases */)
{
/* renderer_string, version_string, vendor_string;*/
const CoglGpuInfoStrings test_strings[2] = {
{ NULL, "3.1 Mesa 9.2-devel15436ad", NULL },
{ NULL, "3.1 (Core Profile) Mesa 9.2.0-devel (git-15436ad)", NULL }
};
int i;
int version;
for (i = 0; i < G_N_ELEMENTS (test_strings); i++)
{
g_assert (check_mesa_driver_package (&test_strings[i], &version));
g_assert_cmpint (version, ==, COGL_VERSION_ENCODE (9, 2, 0));
}
}
static gboolean
check_unknown_driver_package (const CoglGpuInfoStrings *strings,
int *version_out)
{
*version_out = 0;
/* This is a last resort so it always matches */
return TRUE;
}
static const CoglGpuInfoDriverPackageDescription
_cogl_gpu_info_driver_packages[] =
{
{
COGL_GPU_INFO_DRIVER_PACKAGE_MESA,
"Mesa",
check_mesa_driver_package
},
/* Must be last */
{
COGL_GPU_INFO_DRIVER_PACKAGE_UNKNOWN,
"Unknown",
check_unknown_driver_package
}
};
void
_cogl_gpu_info_init (CoglContext *ctx,
CoglGpuInfo *gpu)
{
CoglGpuInfoStrings strings;
int i;
strings.renderer_string = (const char *) ctx->glGetString (GL_RENDERER);
strings.version_string = _cogl_context_get_gl_version (ctx);
strings.vendor_string = (const char *) ctx->glGetString (GL_VENDOR);
/* Determine the driver package */
for (i = 0; ; i++)
{
const CoglGpuInfoDriverPackageDescription *description =
_cogl_gpu_info_driver_packages + i;
if (description->check_function (&strings, &gpu->driver_package_version))
{
gpu->driver_package = description->driver_package;
gpu->driver_package_name = description->name;
break;
}
}
/* Determine the GPU vendor */
for (i = 0; ; i++)
{
const CoglGpuInfoVendorDescription *description =
_cogl_gpu_info_vendors + i;
if (description->check_function (&strings))
{
int j;
gpu->vendor = description->vendor;
gpu->vendor_name = description->name;
for (j = 0; ; j++)
{
const CoglGpuInfoArchitectureDescription *architecture =
description->architectures + j;
if (architecture->check_function (&strings))
{
gpu->architecture = architecture->architecture;
gpu->architecture_name = architecture->name;
gpu->architecture_flags = architecture->flags;
goto probed;
}
}
}
}
probed:
COGL_NOTE (WINSYS, "Driver package = %s, vendor = %s, architecture = %s\n",
gpu->driver_package_name,
gpu->vendor_name,
gpu->architecture_name);
/* Determine the driver bugs */
gpu->driver_bugs = 0;
}

View File

@@ -41,7 +41,6 @@
#include "cogl-matrix-private.h"
#include "cogl-magazine-private.h"
#include "cogl-gtype-private.h"
#include "driver/gl/cogl-util-gl-private.h"
static void _cogl_matrix_stack_free (CoglMatrixStack *stack);

View File

@@ -44,7 +44,6 @@
#include "cogl-node-private.h"
#include "cogl-context-private.h"
#include "cogl-texture-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include <string.h>
@@ -342,8 +341,6 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
CoglPipelineLayer *layer,
CoglPipelineLayerState change)
{
CoglTextureUnit *unit;
/* Identify the case where the layer is new with no owner or
* dependants and so we don't need to do anything. */
if (_cogl_list_empty (&COGL_NODE (layer)->children) &&
@@ -403,15 +400,6 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
progend->layer_pre_change_notify (required_owner, layer, change);
}
/* If the layer being changed is the same as the last layer we
* flushed to the corresponding texture unit then we keep a track of
* the changes so we can try to minimize redundant OpenGL calls if
* the same layer is flushed again.
*/
unit = _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer));
if (unit->layer == layer)
unit->layer_changes_since_flush |= change;
init_layer_state:
if (required_owner)

View File

@@ -51,22 +51,6 @@
#include "cogl-pixel-buffer.h"
#include "cogl-gtype-private.h"
/*
* GL/GLES compatibility defines for the buffer API:
*/
#if defined (HAVE_COGL_GL)
#ifndef GL_PIXEL_UNPACK_BUFFER
#define GL_PIXEL_UNPACK_BUFFER GL_PIXEL_UNPACK_BUFFER_ARB
#endif
#ifndef GL_PIXEL_PACK_BUFFER
#define GL_PIXEL_PACK_BUFFER GL_PIXEL_PACK_BUFFER_ARB
#endif
#endif
static void
_cogl_pixel_buffer_free (CoglPixelBuffer *buffer);

View File

@@ -34,11 +34,6 @@
#include "cogl-sampler-cache-private.h"
#include "cogl-context-private.h"
#include "driver/gl/cogl-util-gl-private.h"
#ifndef GL_TEXTURE_WRAP_R
#define GL_TEXTURE_WRAP_R 0x8072
#endif
struct _CoglSamplerCache
{
@@ -54,10 +49,6 @@ struct _CoglSamplerCache
GL state. */
GHashTable *hash_table_cogl;
GHashTable *hash_table_gl;
/* This is used for generated fake unique sampler object numbers
when the sampler object extension is not supported */
GLuint next_fake_sampler_object_number;
};
static CoglSamplerCacheWrapMode
@@ -176,22 +167,10 @@ _cogl_sampler_cache_new (CoglContext *context)
sampler_state_equal_gl);
cache->hash_table_cogl = g_hash_table_new (hash_sampler_state_cogl,
sampler_state_equal_cogl);
cache->next_fake_sampler_object_number = 1;
return cache;
}
static void
set_wrap_mode (CoglContext *context,
GLuint sampler_object,
GLenum param,
CoglSamplerCacheWrapMode wrap_mode)
{
GE( context, glSamplerParameteri (sampler_object,
param,
wrap_mode) );
}
static CoglSamplerCacheEntry *
_cogl_sampler_cache_get_entry_gl (CoglSamplerCache *cache,
const CoglSamplerCacheEntry *key)
@@ -202,39 +181,9 @@ _cogl_sampler_cache_get_entry_gl (CoglSamplerCache *cache,
if (entry == NULL)
{
CoglContext *context = cache->context;
entry = g_slice_dup (CoglSamplerCacheEntry, key);
if (_cogl_has_private_feature (context,
COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
{
GE( context, glGenSamplers (1, &entry->sampler_object) );
GE( context, glSamplerParameteri (entry->sampler_object,
GL_TEXTURE_MIN_FILTER,
entry->min_filter) );
GE( context, glSamplerParameteri (entry->sampler_object,
GL_TEXTURE_MAG_FILTER,
entry->mag_filter) );
set_wrap_mode (context,
entry->sampler_object,
GL_TEXTURE_WRAP_S,
entry->wrap_mode_s);
set_wrap_mode (context,
entry->sampler_object,
GL_TEXTURE_WRAP_T,
entry->wrap_mode_t);
}
else
{
/* If sampler objects aren't supported then we'll invent a
unique number so that pipelines can still compare the
unique state just by comparing the sampler object
numbers */
entry->sampler_object = cache->next_fake_sampler_object_number++;
}
cache->context->driver_vtable->sampler_init (cache->context, entry);
g_hash_table_insert (cache->hash_table_gl, entry, entry);
}
@@ -320,9 +269,7 @@ hash_table_free_gl_cb (void *key,
CoglContext *context = user_data;
CoglSamplerCacheEntry *entry = value;
if (_cogl_has_private_feature (context,
COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
GE( context, glDeleteSamplers (1, &entry->sampler_object) );
context->driver_vtable->sampler_free (context, entry);
g_slice_free (CoglSamplerCacheEntry, entry);
}

View File

@@ -62,11 +62,6 @@
#include <stdlib.h>
#include <math.h>
/* This isn't defined in the GLES headers */
#ifndef GL_RED
#define GL_RED 0x1903
#endif
COGL_GTYPE_DEFINE_INTERFACE (Texture, texture);
uint32_t
@@ -786,8 +781,6 @@ cogl_texture_get_data (CoglTexture *texture,
if (texture_format == COGL_PIXEL_FORMAT_A_8)
{
closest_format = COGL_PIXEL_FORMAT_A_8;
closest_gl_format = GL_RED;
closest_gl_type = GL_UNSIGNED_BYTE;
}
else if (format == COGL_PIXEL_FORMAT_A_8)
{
@@ -798,8 +791,6 @@ cogl_texture_get_data (CoglTexture *texture,
* pre-multiplied here because we're only going to look at
* the alpha component */
closest_format = COGL_PIXEL_FORMAT_RGBA_8888;
closest_gl_format = GL_RGBA;
closest_gl_type = GL_UNSIGNED_BYTE;
}
}

View File

@@ -31,7 +31,6 @@
#include "cogl-config.h"
#include "cogl-util.h"
#include "driver/gl/cogl-util-gl-private.h"
#include "cogl-context-private.h"
#include "cogl-object-private.h"

View File

@@ -47,16 +47,4 @@ struct _CoglShader
char *source;
};
void
_cogl_shader_compile_real (CoglHandle handle,
CoglPipeline *pipeline);
void
_cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
GLenum shader_gl_type,
int n_tex_coord_attribs,
GLsizei count_in,
const char **strings_in,
const GLint *lengths_in);
#endif /* __COGL_SHADER_H */

View File

@@ -32,7 +32,6 @@
#include "cogl-context-private.h"
#include "cogl-object-private.h"
#include "cogl-glsl-shader-private.h"
#include "cogl-glsl-shader-boilerplate.h"
#include "driver/gl/cogl-util-gl-private.h"
#include "deprecated/cogl-shader-private.h"
@@ -45,13 +44,6 @@ static void _cogl_shader_free (CoglShader *shader);
COGL_HANDLE_DEFINE (Shader, shader);
#ifndef GL_FRAGMENT_SHADER
#define GL_FRAGMENT_SHADER 0x8B30
#endif
#ifndef GL_VERTEX_SHADER
#define GL_VERTEX_SHADER 0x8B31
#endif
static void
_cogl_shader_free (CoglShader *shader)
{
@@ -91,23 +83,6 @@ cogl_create_shader (CoglShaderType type)
return _cogl_shader_handle_new (shader);
}
static void
delete_shader (CoglShader *shader)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (shader->gl_handle)
GE (ctx, glDeleteShader (shader->gl_handle));
shader->gl_handle = 0;
if (shader->compilation_pipeline)
{
cogl_object_unref (shader->compilation_pipeline);
shader->compilation_pipeline = NULL;
}
}
void
cogl_shader_source (CoglHandle handle,
const char *source)
@@ -124,77 +99,6 @@ cogl_shader_source (CoglHandle handle,
shader->source = g_strdup (source);
}
void
_cogl_shader_compile_real (CoglHandle handle,
CoglPipeline *pipeline)
{
CoglShader *shader = handle;
GLenum gl_type;
GLint status;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (shader->gl_handle)
{
CoglPipeline *prev = shader->compilation_pipeline;
/* XXX: currently the only things that will affect the
* boilerplate for user shaders, apart from driver features,
* are the pipeline layer-indices and texture-unit-indices
*/
if (pipeline == prev ||
_cogl_pipeline_layer_and_unit_numbers_equal (prev, pipeline))
return;
}
if (shader->gl_handle)
delete_shader (shader);
switch (shader->type)
{
case COGL_SHADER_TYPE_VERTEX:
gl_type = GL_VERTEX_SHADER;
break;
case COGL_SHADER_TYPE_FRAGMENT:
gl_type = GL_FRAGMENT_SHADER;
break;
default:
g_assert_not_reached ();
break;
}
shader->gl_handle = ctx->glCreateShader (gl_type);
_cogl_glsl_shader_set_source_with_boilerplate (ctx,
shader->gl_handle,
gl_type,
pipeline,
1,
(const char **)
&shader->source,
NULL);
GE (ctx, glCompileShader (shader->gl_handle));
shader->compilation_pipeline = cogl_object_ref (pipeline);
GE (ctx, glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
if (!status)
{
char buffer[512];
int len = 0;
ctx->glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
buffer[len] = '\0';
g_warning ("Failed to compile GLSL program:\n"
"src:\n%s\n"
"error:\n%s\n",
shader->source,
buffer);
}
}
CoglShaderType
cogl_shader_get_type (CoglHandle handle)
{

View File

@@ -43,11 +43,11 @@
#include "cogl-snippet-private.h"
#include "cogl-list.h"
#include "driver/gl/cogl-util-gl-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include "cogl-context-private.h"
#include "cogl-object-private.h"
#include "cogl-pipeline-cache.h"
#include "cogl-glsl-shader-private.h"
#include "driver/gl/cogl-pipeline-fragend-glsl-private.h"
#include "deprecated/cogl-shader-private.h"
#include "deprecated/cogl-program-private.h"

View File

@@ -146,5 +146,27 @@ _cogl_pipeline_flush_gl_state (CoglContext *context,
gboolean skip_gl_state,
gboolean unknown_color_alpha);
void
_cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx,
GLuint shader_gl_handle,
GLenum shader_gl_type,
CoglPipeline *pipeline,
GLsizei count_in,
const char **strings_in,
const GLint *lengths_in);
void
_cogl_sampler_gl_init (CoglContext *context,
CoglSamplerCacheEntry *entry);
void
_cogl_sampler_gl_free (CoglContext *context,
CoglSamplerCacheEntry *entry);
void
_cogl_gl_set_uniform (CoglContext *ctx,
GLint location,
const CoglBoxedValue *value);
#endif /* __COGL_PIPELINE_OPENGL_PRIVATE_H */

View File

@@ -94,47 +94,51 @@ CoglTextureUnit *
_cogl_get_texture_unit (int index_)
{
_COGL_GET_CONTEXT (ctx, NULL);
CoglGLContext *glctx = _cogl_driver_gl_context(ctx);
if (ctx->texture_units->len < (index_ + 1))
if (glctx->texture_units->len < (index_ + 1))
{
int i;
int prev_len = ctx->texture_units->len;
ctx->texture_units = g_array_set_size (ctx->texture_units, index_ + 1);
int prev_len = glctx->texture_units->len;
glctx->texture_units = g_array_set_size (glctx->texture_units,
index_ + 1);
for (i = prev_len; i <= index_; i++)
{
CoglTextureUnit *unit =
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
&g_array_index (glctx->texture_units, CoglTextureUnit, i);
texture_unit_init (ctx, unit, i);
}
}
return &g_array_index (ctx->texture_units, CoglTextureUnit, index_);
return &g_array_index (glctx->texture_units, CoglTextureUnit, index_);
}
void
_cogl_destroy_texture_units (CoglContext *ctx)
{
int i;
CoglGLContext *glctx = _cogl_driver_gl_context(ctx);
for (i = 0; i < ctx->texture_units->len; i++)
for (i = 0; i < glctx->texture_units->len; i++)
{
CoglTextureUnit *unit =
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
&g_array_index (glctx->texture_units, CoglTextureUnit, i);
texture_unit_free (unit);
}
g_array_free (ctx->texture_units, TRUE);
g_array_free (glctx->texture_units, TRUE);
}
void
_cogl_set_active_texture_unit (int unit_index)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
CoglGLContext *glctx = _cogl_driver_gl_context(ctx);
if (ctx->active_texture_unit != unit_index)
if (glctx->active_texture_unit != unit_index)
{
GE (ctx, glActiveTexture (GL_TEXTURE0 + unit_index));
ctx->active_texture_unit = unit_index;
glctx->active_texture_unit = unit_index;
}
}
@@ -190,11 +194,12 @@ _cogl_delete_gl_texture (GLuint gl_texture)
int i;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
CoglGLContext *glctx = _cogl_driver_gl_context(ctx);
for (i = 0; i < ctx->texture_units->len; i++)
for (i = 0; i < glctx->texture_units->len; i++)
{
CoglTextureUnit *unit =
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
&g_array_index (glctx->texture_units, CoglTextureUnit, i);
if (unit->gl_texture == gl_texture)
{
@@ -218,11 +223,12 @@ _cogl_pipeline_texture_storage_change_notify (CoglTexture *texture)
int i;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
CoglGLContext *glctx = _cogl_driver_gl_context(ctx);
for (i = 0; i < ctx->texture_units->len; i++)
for (i = 0; i < glctx->texture_units->len; i++)
{
CoglTextureUnit *unit =
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
&g_array_index (glctx->texture_units, CoglTextureUnit, i);
if (unit->layer &&
_cogl_pipeline_layer_get_texture (unit->layer) == texture)
@@ -688,6 +694,48 @@ _cogl_pipeline_layer_forward_wrap_modes (CoglPipelineLayer *layer,
gl_wrap_mode_t);
}
void
_cogl_sampler_gl_init (CoglContext *context, CoglSamplerCacheEntry *entry)
{
if (_cogl_has_private_feature (context,
COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
{
GE( context, glGenSamplers (1, &entry->sampler_object) );
GE( context, glSamplerParameteri (entry->sampler_object,
GL_TEXTURE_MIN_FILTER,
entry->min_filter) );
GE( context, glSamplerParameteri (entry->sampler_object,
GL_TEXTURE_MAG_FILTER,
entry->mag_filter) );
GE (context, glSamplerParameteri (entry->sampler_object,
GL_TEXTURE_WRAP_S,
entry->wrap_mode_s) );
GE (context, glSamplerParameteri (entry->sampler_object,
GL_TEXTURE_WRAP_T,
entry->wrap_mode_t) );
}
else
{
CoglGLContext *gl_context = context->driver_context;
/* If sampler objects aren't supported then we'll invent a
unique number so that pipelines can still compare the
unique state just by comparing the sampler object
numbers */
entry->sampler_object = gl_context->next_fake_sampler_object_number++;
}
}
void
_cogl_sampler_gl_free (CoglContext *context, CoglSamplerCacheEntry *entry)
{
if (_cogl_has_private_feature (context,
COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
GE( context, glDeleteSamplers (1, &entry->sampler_object) );
}
/* OpenGL associates the min/mag filters and repeat modes with the
* texture object not the texture unit so we always have to re-assert
* the filter and repeat modes whenever we use a texture since it may
@@ -704,11 +752,12 @@ foreach_texture_unit_update_filter_and_wrap_modes (void)
int i;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
CoglGLContext *glctx = _cogl_driver_gl_context(ctx);
for (i = 0; i < ctx->texture_units->len; i++)
for (i = 0; i < glctx->texture_units->len; i++)
{
CoglTextureUnit *unit =
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
&g_array_index (glctx->texture_units, CoglTextureUnit, i);
if (unit->layer)
{
@@ -1141,3 +1190,95 @@ done:
COGL_TIMER_STOP (_cogl_uprof_context, pipeline_flush_timer);
}
void
_cogl_gl_set_uniform (CoglContext *ctx,
GLint location,
const CoglBoxedValue *value)
{
switch (value->type)
{
case COGL_BOXED_NONE:
break;
case COGL_BOXED_INT:
{
const int *ptr;
if (value->count == 1)
ptr = value->v.int_value;
else
ptr = value->v.int_array;
switch (value->size)
{
case 1:
GE( ctx, glUniform1iv (location, value->count, ptr) );
break;
case 2:
GE( ctx, glUniform2iv (location, value->count, ptr) );
break;
case 3:
GE( ctx, glUniform3iv (location, value->count, ptr) );
break;
case 4:
GE( ctx, glUniform4iv (location, value->count, ptr) );
break;
}
}
break;
case COGL_BOXED_FLOAT:
{
const float *ptr;
if (value->count == 1)
ptr = value->v.float_value;
else
ptr = value->v.float_array;
switch (value->size)
{
case 1:
GE( ctx, glUniform1fv (location, value->count, ptr) );
break;
case 2:
GE( ctx, glUniform2fv (location, value->count, ptr) );
break;
case 3:
GE( ctx, glUniform3fv (location, value->count, ptr) );
break;
case 4:
GE( ctx, glUniform4fv (location, value->count, ptr) );
break;
}
}
break;
case COGL_BOXED_MATRIX:
{
const float *ptr;
if (value->count == 1)
ptr = value->v.matrix;
else
ptr = value->v.float_array;
switch (value->size)
{
case 2:
GE( ctx, glUniformMatrix2fv (location, value->count,
FALSE, ptr) );
break;
case 3:
GE( ctx, glUniformMatrix3fv (location, value->count,
FALSE, ptr) );
break;
case 4:
GE( ctx, glUniformMatrix4fv (location, value->count,
FALSE, ptr) );
break;
}
}
break;
}
}

View File

@@ -633,6 +633,82 @@ _cogl_pipeline_progend_glsl_start (CoglPipeline *pipeline)
return TRUE;
}
static void
_cogl_shader_compile_real (CoglHandle handle,
CoglPipeline *pipeline)
{
CoglShader *shader = handle;
GLenum gl_type;
GLint status;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (shader->gl_handle)
{
CoglPipeline *prev = shader->compilation_pipeline;
/* XXX: currently the only things that will affect the
* boilerplate for user shaders, apart from driver features,
* are the pipeline layer-indices and texture-unit-indices
*/
if (pipeline == prev ||
_cogl_pipeline_layer_and_unit_numbers_equal (prev, pipeline))
return;
GE (ctx, glDeleteShader (shader->gl_handle));
shader->gl_handle = 0;
if (shader->compilation_pipeline)
{
cogl_object_unref (shader->compilation_pipeline);
shader->compilation_pipeline = NULL;
}
}
switch (shader->type)
{
case COGL_SHADER_TYPE_VERTEX:
gl_type = GL_VERTEX_SHADER;
break;
case COGL_SHADER_TYPE_FRAGMENT:
gl_type = GL_FRAGMENT_SHADER;
break;
default:
g_assert_not_reached ();
break;
}
shader->gl_handle = ctx->glCreateShader (gl_type);
_cogl_glsl_shader_set_source_with_boilerplate (ctx,
shader->gl_handle,
gl_type,
pipeline,
1,
(const char **)
&shader->source,
NULL);
GE (ctx, glCompileShader (shader->gl_handle));
shader->compilation_pipeline = cogl_object_ref (pipeline);
GE (ctx, glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
if (!status)
{
char buffer[512];
int len = 0;
ctx->glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
buffer[len] = '\0';
g_warning ("Failed to compile GLSL program:\n"
"src:\n%s\n"
"error:\n%s\n",
shader->source,
buffer);
}
}
static void
_cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
unsigned long pipelines_difference)
@@ -877,6 +953,7 @@ _cogl_pipeline_progend_glsl_layer_pre_change_notify (
CoglPipelineLayerState change)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
CoglTextureUnit *unit;
if ((change & (_cogl_pipeline_get_layer_state_for_fragment_codegen (ctx) |
COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN)))
@@ -901,6 +978,15 @@ _cogl_pipeline_progend_glsl_layer_pre_change_notify (
program_state->unit_state[unit_index].dirty_texture_matrix = TRUE;
}
}
/* If the layer being changed is the same as the last layer we
* flushed to the corresponding texture unit then we keep a track of
* the changes so we can try to minimize redundant OpenGL calls if
* the same layer is flushed again.
*/
unit = _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer));
if (unit->layer == layer)
unit->layer_changes_since_flush |= change;
}
static void

View File

@@ -45,7 +45,7 @@
#include "cogl-context-private.h"
#include "cogl-object-private.h"
#include "cogl-pipeline-state-private.h"
#include "cogl-glsl-shader-private.h"
#include "cogl-glsl-shader-boilerplate.h"
#include "driver/gl/cogl-pipeline-vertend-glsl-private.h"
#include "deprecated/cogl-program-private.h"
@@ -132,6 +132,150 @@ dirty_shader_state (CoglPipeline *pipeline)
NULL);
}
static gboolean
add_layer_vertex_boilerplate_cb (CoglPipelineLayer *layer,
void *user_data)
{
GString *layer_declarations = user_data;
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
g_string_append_printf (layer_declarations,
"attribute vec4 cogl_tex_coord%d_in;\n"
"#define cogl_texture_matrix%i cogl_texture_matrix[%i]\n"
"#define cogl_tex_coord%i_out _cogl_tex_coord[%i]\n",
layer->index,
layer->index,
unit_index,
layer->index,
unit_index);
return TRUE;
}
static gboolean
add_layer_fragment_boilerplate_cb (CoglPipelineLayer *layer,
void *user_data)
{
GString *layer_declarations = user_data;
g_string_append_printf (layer_declarations,
"#define cogl_tex_coord%i_in _cogl_tex_coord[%i]\n",
layer->index,
_cogl_pipeline_layer_get_unit_index (layer));
return TRUE;
}
void
_cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx,
GLuint shader_gl_handle,
GLenum shader_gl_type,
CoglPipeline *pipeline,
GLsizei count_in,
const char **strings_in,
const GLint *lengths_in)
{
const char *vertex_boilerplate;
const char *fragment_boilerplate;
const char **strings = g_alloca (sizeof (char *) * (count_in + 4));
GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 4));
char *version_string;
int count = 0;
int n_layers;
vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE;
fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE;
version_string = g_strdup_printf ("#version %i\n\n",
ctx->glsl_version_to_use);
strings[count] = version_string;
lengths[count++] = -1;
if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL))
{
static const char image_external_extension[] =
"#extension GL_OES_EGL_image_external : require\n";
strings[count] = image_external_extension;
lengths[count++] = sizeof (image_external_extension) - 1;
}
if (shader_gl_type == GL_VERTEX_SHADER)
{
strings[count] = vertex_boilerplate;
lengths[count++] = strlen (vertex_boilerplate);
}
else if (shader_gl_type == GL_FRAGMENT_SHADER)
{
strings[count] = fragment_boilerplate;
lengths[count++] = strlen (fragment_boilerplate);
}
n_layers = cogl_pipeline_get_n_layers (pipeline);
if (n_layers)
{
GString *layer_declarations = ctx->codegen_boilerplate_buffer;
g_string_set_size (layer_declarations, 0);
g_string_append_printf (layer_declarations,
"varying vec4 _cogl_tex_coord[%d];\n",
n_layers);
if (shader_gl_type == GL_VERTEX_SHADER)
{
g_string_append_printf (layer_declarations,
"uniform mat4 cogl_texture_matrix[%d];\n",
n_layers);
_cogl_pipeline_foreach_layer_internal (pipeline,
add_layer_vertex_boilerplate_cb,
layer_declarations);
}
else if (shader_gl_type == GL_FRAGMENT_SHADER)
{
_cogl_pipeline_foreach_layer_internal (pipeline,
add_layer_fragment_boilerplate_cb,
layer_declarations);
}
strings[count] = layer_declarations->str;
lengths[count++] = -1; /* null terminated */
}
memcpy (strings + count, strings_in, sizeof (char *) * count_in);
if (lengths_in)
memcpy (lengths + count, lengths_in, sizeof (GLint) * count_in);
else
{
int i;
for (i = 0; i < count_in; i++)
lengths[count + i] = -1; /* null terminated */
}
count += count_in;
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
{
GString *buf = g_string_new (NULL);
int i;
g_string_append_printf (buf,
"%s shader:\n",
shader_gl_type == GL_VERTEX_SHADER ?
"vertex" : "fragment");
for (i = 0; i < count; i++)
if (lengths[i] != -1)
g_string_append_len (buf, strings[i], lengths[i]);
else
g_string_append (buf, strings[i]);
g_message ("%s", buf->str);
g_string_free (buf, TRUE);
}
GE( ctx, glShaderSource (shader_gl_handle, count,
(const char **) strings, lengths) );
g_free (version_string);
}
GLuint
_cogl_pipeline_vertend_glsl_get_shader (CoglPipeline *pipeline)
{

View File

@@ -76,6 +76,18 @@ _cogl_gl_error_to_string (GLenum error_code);
#endif /* COGL_GL_DEBUG */
typedef struct _CoglGLContext {
GArray *texture_units;
int active_texture_unit;
/* This is used for generated fake unique sampler object numbers
when the sampler object extension is not supported */
GLuint next_fake_sampler_object_number;
} CoglGLContext;
CoglGLContext *
_cogl_driver_gl_context (CoglContext *context);
gboolean
_cogl_driver_gl_context_init (CoglContext *context);
@@ -91,6 +103,23 @@ _cogl_gl_util_clear_gl_errors (CoglContext *ctx);
gboolean
_cogl_gl_util_catch_out_of_memory (CoglContext *ctx, GError **error);
gboolean
_cogl_driver_gl_is_hardware_accelerated (CoglContext *context);
/*
* _cogl_context_get_gl_extensions:
* @context: A CoglContext
*
* Return value: a NULL-terminated array of strings representing the
* supported extensions by the current driver. This array is owned
* by the caller and should be freed with g_strfreev().
*/
char **
_cogl_context_get_gl_extensions (CoglContext *context);
const char *
_cogl_context_get_gl_version (CoglContext *context);
/* Parses a GL version number stored in a string. @version_string must
* point to the beginning of the version number (ie, it can't point to
* the "OpenGL ES" part on GLES). The version number can be followed
@@ -102,4 +131,7 @@ _cogl_gl_util_parse_gl_version (const char *version_string,
int *major_out,
int *minor_out);
CoglGraphicsResetStatus
_cogl_gl_get_graphics_reset_status (CoglContext *context);
#endif /* _COGL_UTIL_GL_PRIVATE_H_ */

View File

@@ -37,6 +37,24 @@
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include "driver/gl/cogl-util-gl-private.h"
/* This is a relatively new extension */
#ifndef GL_PURGED_CONTEXT_RESET_NV
#define GL_PURGED_CONTEXT_RESET_NV 0x92BB
#endif
/* These aren't defined in the GLES2 headers */
#ifndef GL_GUILTY_CONTEXT_RESET_ARB
#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
#endif
#ifndef GL_INNOCENT_CONTEXT_RESET_ARB
#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
#endif
#ifndef GL_UNKNOWN_CONTEXT_RESET_ARB
#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
#endif
#ifdef COGL_GL_DEBUG
/* GL error to string conversion */
static const struct {
@@ -75,15 +93,31 @@ _cogl_gl_error_to_string (GLenum error_code)
}
#endif /* COGL_GL_DEBUG */
CoglGLContext *
_cogl_driver_gl_context (CoglContext *context)
{
return context->driver_context;
}
gboolean
_cogl_driver_gl_context_init (CoglContext *context)
{
context->texture_units =
CoglGLContext *gl_context;
if (!context->driver_context)
context->driver_context = g_new0 (CoglContext, 1);
gl_context = _cogl_driver_gl_context (context);
if (!gl_context)
return FALSE;
gl_context->next_fake_sampler_object_number = 1;
gl_context->texture_units =
g_array_new (FALSE, FALSE, sizeof (CoglTextureUnit));
/* See cogl-pipeline.c for more details about why we leave texture unit 1
* active by default... */
context->active_texture_unit = 1;
gl_context->active_texture_unit = 1;
GE (context, glActiveTexture (GL_TEXTURE1));
return TRUE;
@@ -93,6 +127,7 @@ void
_cogl_driver_gl_context_deinit (CoglContext *context)
{
_cogl_destroy_texture_units (context);
g_free (context->driver_context);
}
GLenum
@@ -147,6 +182,94 @@ _cogl_gl_util_catch_out_of_memory (CoglContext *ctx, GError **error)
return FALSE;
}
char **
_cogl_context_get_gl_extensions (CoglContext *context)
{
const char *env_disabled_extensions;
char **ret;
/* In GL 3, querying GL_EXTENSIONS is deprecated so we have to build
* the array using glGetStringi instead */
#ifdef HAVE_COGL_GL
if (context->driver == COGL_DRIVER_GL3)
{
int num_extensions, i;
context->glGetIntegerv (GL_NUM_EXTENSIONS, &num_extensions);
ret = g_malloc (sizeof (char *) * (num_extensions + 1));
for (i = 0; i < num_extensions; i++)
{
const char *ext =
(const char *) context->glGetStringi (GL_EXTENSIONS, i);
ret[i] = g_strdup (ext);
}
ret[num_extensions] = NULL;
}
else
#endif
{
const char *all_extensions =
(const char *) context->glGetString (GL_EXTENSIONS);
ret = g_strsplit (all_extensions, " ", 0 /* max tokens */);
}
if ((env_disabled_extensions = g_getenv ("COGL_DISABLE_GL_EXTENSIONS")))
{
char **split_env_disabled_extensions;
char **src, **dst;
if (env_disabled_extensions)
split_env_disabled_extensions =
g_strsplit (env_disabled_extensions,
",",
0 /* no max tokens */);
else
split_env_disabled_extensions = NULL;
for (dst = ret, src = ret;
*src;
src++)
{
char **d;
if (split_env_disabled_extensions)
for (d = split_env_disabled_extensions; *d; d++)
if (!strcmp (*src, *d))
goto disabled;
*(dst++) = *src;
continue;
disabled:
g_free (*src);
continue;
}
*dst = NULL;
if (split_env_disabled_extensions)
g_strfreev (split_env_disabled_extensions);
}
return ret;
}
const char *
_cogl_context_get_gl_version (CoglContext *context)
{
const char *version_override;
if ((version_override = g_getenv ("COGL_OVERRIDE_GL_VERSION")))
return version_override;
else
return (const char *) context->glGetString (GL_VERSION);
}
gboolean
_cogl_gl_util_parse_gl_version (const char *version_string,
int *major_out,
@@ -179,3 +302,53 @@ _cogl_gl_util_parse_gl_version (const char *version_string,
return TRUE;
}
/*
* This should arguably use something like GLX_MESA_query_renderer, but
* a) that's GLX-only, and you could add it to EGL too but
* b) that'd make this a winsys query when really it's not a property of
* the winsys but the renderer, and
* c) only Mesa really supports it anyway, and
* d) Mesa is the only software renderer of interest.
*
* So instead just check a list of known software renderer strings.
*/
gboolean
_cogl_driver_gl_is_hardware_accelerated (CoglContext *ctx)
{
const char *renderer = (const char *) ctx->glGetString (GL_RENDERER);
gboolean software;
software = strstr (renderer, "llvmpipe") != NULL ||
strstr (renderer, "softpipe") != NULL ||
strstr (renderer, "software rasterizer") != NULL ||
strstr (renderer, "Software Rasterizer") != NULL ||
strstr (renderer, "SWR");
return !software;
}
CoglGraphicsResetStatus
_cogl_gl_get_graphics_reset_status (CoglContext *context)
{
if (!context->glGetGraphicsResetStatus)
return COGL_GRAPHICS_RESET_STATUS_NO_ERROR;
switch (context->glGetGraphicsResetStatus ())
{
case GL_GUILTY_CONTEXT_RESET_ARB:
return COGL_GRAPHICS_RESET_STATUS_GUILTY_CONTEXT_RESET;
case GL_INNOCENT_CONTEXT_RESET_ARB:
return COGL_GRAPHICS_RESET_STATUS_INNOCENT_CONTEXT_RESET;
case GL_UNKNOWN_CONTEXT_RESET_ARB:
return COGL_GRAPHICS_RESET_STATUS_UNKNOWN_CONTEXT_RESET;
case GL_PURGED_CONTEXT_RESET_NV:
return COGL_GRAPHICS_RESET_STATUS_PURGED_CONTEXT_RESET;
default:
return COGL_GRAPHICS_RESET_STATUS_NO_ERROR;
}
}

View File

@@ -42,6 +42,7 @@
#include "driver/gl/cogl-attribute-gl-private.h"
#include "driver/gl/cogl-clip-stack-gl-private.h"
#include "driver/gl/cogl-buffer-gl-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
static gboolean
_cogl_driver_gl_real_context_init (CoglContext *context)
@@ -419,8 +420,6 @@ _cogl_driver_update_features (CoglContext *ctx,
_cogl_get_gl_version (ctx, &gl_major, &gl_minor);
_cogl_gpu_info_init (ctx, &ctx->gpu);
ctx->glsl_major = 1;
ctx->glsl_minor = 2;
ctx->glsl_version_to_use = 120;
@@ -532,6 +531,8 @@ _cogl_driver_gl =
{
_cogl_driver_gl_real_context_init,
_cogl_driver_gl_context_deinit,
_cogl_driver_gl_is_hardware_accelerated,
_cogl_gl_get_graphics_reset_status,
_cogl_driver_pixel_format_from_gl_internal,
_cogl_driver_pixel_format_to_gl,
_cogl_driver_update_features,
@@ -563,4 +564,7 @@ _cogl_driver_gl =
_cogl_buffer_gl_map_range,
_cogl_buffer_gl_unmap,
_cogl_buffer_gl_set_data,
_cogl_sampler_gl_init,
_cogl_sampler_gl_free,
_cogl_gl_set_uniform, /* XXX name is weird... */
};

View File

@@ -42,6 +42,7 @@
#include "driver/gl/cogl-attribute-gl-private.h"
#include "driver/gl/cogl-clip-stack-gl-private.h"
#include "driver/gl/cogl-buffer-gl-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#ifndef GL_UNSIGNED_INT_24_8
#define GL_UNSIGNED_INT_24_8 0x84FA
@@ -282,8 +283,6 @@ _cogl_driver_update_features (CoglContext *context,
context->glsl_minor = 0;
context->glsl_version_to_use = 100;
_cogl_gpu_info_init (context, &context->gpu);
if (!_cogl_get_gl_version (context, &gl_major, &gl_minor))
{
gl_major = 1;
@@ -396,6 +395,8 @@ _cogl_driver_gles =
{
_cogl_driver_gl_context_init,
_cogl_driver_gl_context_deinit,
_cogl_driver_gl_is_hardware_accelerated,
_cogl_gl_get_graphics_reset_status,
_cogl_driver_pixel_format_from_gl_internal,
_cogl_driver_pixel_format_to_gl,
_cogl_driver_update_features,
@@ -427,4 +428,7 @@ _cogl_driver_gles =
_cogl_buffer_gl_map_range,
_cogl_buffer_gl_unmap,
_cogl_buffer_gl_set_data,
_cogl_sampler_gl_init,
_cogl_sampler_gl_free,
_cogl_gl_set_uniform,
};

View File

@@ -45,8 +45,6 @@ static gboolean
_cogl_driver_update_features (CoglContext *ctx,
GError **error)
{
/* _cogl_gpu_info_init (ctx, &ctx->gpu); */
memset (ctx->private_features, 0, sizeof (ctx->private_features));
return TRUE;
@@ -63,11 +61,19 @@ _cogl_driver_nop_context_deinit (CoglContext *context)
{
}
static gboolean
_cogl_driver_nop_is_hardware_accelerated (CoglContext *context)
{
return FALSE;
}
const CoglDriverVtable
_cogl_driver_nop =
{
_cogl_driver_nop_context_init,
_cogl_driver_nop_context_deinit,
_cogl_driver_nop_is_hardware_accelerated,
NULL, /* get_graphics_reset_status */
NULL, /* pixel_format_from_gl_internal */
NULL, /* pixel_format_to_gl */
_cogl_driver_update_features,

View File

@@ -208,8 +208,6 @@ cogl_sources = [
'cogl-debug.h',
'cogl-debug-options.h',
'cogl-dma-buf-handle.c',
'cogl-gpu-info.c',
'cogl-gpu-info-private.h',
'cogl-context-private.h',
'cogl-context.c',
'cogl-renderer-private.h',
@@ -276,8 +274,6 @@ cogl_sources = [
'cogl-pipeline-layer-state.c',
'cogl-pipeline-state-private.h',
'cogl-pipeline-debug.c',
'cogl-glsl-shader.c',
'cogl-glsl-shader-private.h',
'cogl-glsl-shader-boilerplate.h',
'cogl-pipeline-snippet-private.h',
'cogl-pipeline-snippet.c',

View File

@@ -1662,8 +1662,6 @@ set_frame_info_output (CoglOnscreen *onscreen,
{
CoglFrameInfo *info = g_queue_peek_tail (&onscreen->pending_frame_infos);
info->output = output;
if (output)
{
float refresh_rate = cogl_output_get_refresh_rate (output);

View File

@@ -12,7 +12,7 @@ option('opengl_libname',
option('gles2_libname',
type: 'string',
value: 'libGLESv2.so',
value: 'libGLESv2.so.2',
description: 'GLESv2 library file name'
)

View File

@@ -156,10 +156,6 @@ xkb_layout_index_t meta_backend_get_keymap_layout_group (MetaBackend *backend);
gboolean meta_backend_is_lid_closed (MetaBackend *backend);
void meta_backend_freeze_updates (MetaBackend *backend);
void meta_backend_thaw_updates (MetaBackend *backend);
void meta_backend_update_last_device (MetaBackend *backend,
ClutterInputDevice *device);

View File

@@ -21,6 +21,8 @@
#ifndef META_BACKEND_TYPE_H
#define META_BACKEND_TYPE_H
typedef struct _MetaBackend MetaBackend;
typedef struct _MetaMonitorManager MetaMonitorManager;
typedef struct _MetaMonitorConfigManager MetaMonitorConfigManager;
@@ -42,8 +44,9 @@ typedef struct _MetaGpu MetaGpu;
typedef struct _MetaCrtc MetaCrtc;
typedef struct _MetaOutput MetaOutput;
typedef struct _MetaCrtcMode MetaCrtcMode;
typedef struct _MetaCrtcInfo MetaCrtcInfo;
typedef struct _MetaOutputInfo MetaOutputInfo;
typedef struct _MetaCrtcAssignment MetaCrtcAssignment;
typedef struct _MetaOutputAssignment MetaOutputAssignment;
typedef struct _MetaTileInfo MetaTileInfo;
typedef struct _MetaRenderer MetaRenderer;

View File

@@ -575,12 +575,6 @@ meta_backend_real_post_init (MetaBackend *backend)
}
}
static MetaCursorRenderer *
meta_backend_real_create_cursor_renderer (MetaBackend *backend)
{
return meta_cursor_renderer_new ();
}
static gboolean
meta_backend_real_grab_device (MetaBackend *backend,
int device_id,
@@ -762,7 +756,6 @@ meta_backend_class_init (MetaBackendClass *klass)
object_class->constructed = meta_backend_constructed;
klass->post_init = meta_backend_real_post_init;
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
klass->grab_device = meta_backend_real_grab_device;
klass->ungrab_device = meta_backend_real_ungrab_device;
klass->select_stage_events = meta_backend_real_select_stage_events;
@@ -1275,24 +1268,6 @@ meta_backend_get_stage (MetaBackend *backend)
return priv->stage;
}
void
meta_backend_freeze_updates (MetaBackend *backend)
{
ClutterStage *stage;
stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
clutter_stage_freeze_updates (stage);
}
void
meta_backend_thaw_updates (MetaBackend *backend)
{
ClutterStage *stage;
stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
clutter_stage_thaw_updates (stage);
}
static gboolean
update_last_device (MetaBackend *backend)
{

View File

@@ -0,0 +1,200 @@
/*
* Copyright (C) 2017-2020 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include "backends/meta-crtc-mode.h"
enum
{
PROP_0,
PROP_ID,
PROP_NAME,
PROP_INFO,
N_PROPS
};
static GParamSpec *obj_props[N_PROPS];
typedef struct _MetaCrtcModePrivate
{
uint64_t id;
char *name;
MetaCrtcModeInfo *info;
} MetaCrtcModePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCrtcMode, meta_crtc_mode, G_TYPE_OBJECT)
G_DEFINE_BOXED_TYPE (MetaCrtcModeInfo, meta_crtc_mode_info,
meta_crtc_mode_info_ref,
meta_crtc_mode_info_unref)
MetaCrtcModeInfo *
meta_crtc_mode_info_new (void)
{
MetaCrtcModeInfo *crtc_mode_info;
crtc_mode_info = g_new0 (MetaCrtcModeInfo, 1);
g_ref_count_init (&crtc_mode_info->ref_count);
return crtc_mode_info;
}
MetaCrtcModeInfo *
meta_crtc_mode_info_ref (MetaCrtcModeInfo *crtc_mode_info)
{
g_ref_count_inc (&crtc_mode_info->ref_count);
return crtc_mode_info;
}
void
meta_crtc_mode_info_unref (MetaCrtcModeInfo *crtc_mode_info)
{
if (g_ref_count_dec (&crtc_mode_info->ref_count))
g_free (crtc_mode_info);
}
uint64_t
meta_crtc_mode_get_id (MetaCrtcMode *crtc_mode)
{
MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode);
return priv->id;
}
const char *
meta_crtc_mode_get_name (MetaCrtcMode *crtc_mode)
{
MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode);
return priv->name;
}
const MetaCrtcModeInfo *
meta_crtc_mode_get_info (MetaCrtcMode *crtc_mode)
{
MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode);
return priv->info;
}
static void
meta_crtc_mode_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaCrtcMode *crtc_mode = META_CRTC_MODE (object);
MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode);
switch (prop_id)
{
case PROP_ID:
priv->id = g_value_get_uint64 (value);
break;
case PROP_NAME:
priv->name = g_value_dup_string (value);
break;
case PROP_INFO:
priv->info = meta_crtc_mode_info_ref (g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_crtc_mode_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaCrtcMode *crtc_mode = META_CRTC_MODE (object);
MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode);
switch (prop_id)
{
case PROP_ID:
g_value_set_uint64 (value, priv->id);
break;
case PROP_NAME:
g_value_set_string (value, priv->name);
break;
case PROP_INFO:
g_value_set_boxed (value, priv->info);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_crtc_mode_finalize (GObject *object)
{
MetaCrtcMode *crtc_mode = META_CRTC_MODE (object);
MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode);
g_clear_pointer (&priv->name, g_free);
g_clear_pointer (&priv->info, meta_crtc_mode_info_unref);
G_OBJECT_CLASS (meta_crtc_mode_parent_class)->finalize (object);
}
static void
meta_crtc_mode_init (MetaCrtcMode *crtc_mode)
{
}
static void
meta_crtc_mode_class_init (MetaCrtcModeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = meta_crtc_mode_set_property;
object_class->get_property = meta_crtc_mode_get_property;
object_class->finalize = meta_crtc_mode_finalize;
obj_props[PROP_ID] =
g_param_spec_uint64 ("id",
"id",
"CRTC mode id",
0, UINT64_MAX, 0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_NAME] =
g_param_spec_string ("name",
"name",
"Name of CRTC mode",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_INFO] =
g_param_spec_boxed ("info",
"info",
"MetaOutputInfo",
META_TYPE_CRTC_MODE_INFO,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, obj_props);
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2017-2020 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_CRTC_MODE_H
#define META_CRTC_MODE_H
#include <glib-object.h>
#include <stdint.h>
#include "core/util-private.h"
/* Same as KMS mode flags and X11 randr flags */
typedef enum _MetaCrtcModeFlag
{
META_CRTC_MODE_FLAG_NONE = 0,
META_CRTC_MODE_FLAG_PHSYNC = (1 << 0),
META_CRTC_MODE_FLAG_NHSYNC = (1 << 1),
META_CRTC_MODE_FLAG_PVSYNC = (1 << 2),
META_CRTC_MODE_FLAG_NVSYNC = (1 << 3),
META_CRTC_MODE_FLAG_INTERLACE = (1 << 4),
META_CRTC_MODE_FLAG_DBLSCAN = (1 << 5),
META_CRTC_MODE_FLAG_CSYNC = (1 << 6),
META_CRTC_MODE_FLAG_PCSYNC = (1 << 7),
META_CRTC_MODE_FLAG_NCSYNC = (1 << 8),
META_CRTC_MODE_FLAG_HSKEW = (1 << 9),
META_CRTC_MODE_FLAG_BCAST = (1 << 10),
META_CRTC_MODE_FLAG_PIXMUX = (1 << 11),
META_CRTC_MODE_FLAG_DBLCLK = (1 << 12),
META_CRTC_MODE_FLAG_CLKDIV2 = (1 << 13),
META_CRTC_MODE_FLAG_MASK = 0x3fff
} MetaCrtcModeFlag;
typedef struct _MetaCrtcModeInfo
{
grefcount ref_count;
int width;
int height;
float refresh_rate;
MetaCrtcModeFlag flags;
} MetaCrtcModeInfo;
#define META_TYPE_CRTC_MODE (meta_crtc_mode_get_type ())
META_EXPORT_TEST
G_DECLARE_DERIVABLE_TYPE (MetaCrtcMode, meta_crtc_mode,
META, CRTC_MODE,
GObject)
struct _MetaCrtcModeClass
{
GObjectClass parent_class;
};
#define META_TYPE_CRTC_MODE_INFO (meta_crtc_mode_info_get_type ())
GType meta_crtc_mode_info_get_type (void);
META_EXPORT_TEST
MetaCrtcModeInfo * meta_crtc_mode_info_new (void);
META_EXPORT_TEST
MetaCrtcModeInfo * meta_crtc_mode_info_ref (MetaCrtcModeInfo *crtc_mode_info);
META_EXPORT_TEST
void meta_crtc_mode_info_unref (MetaCrtcModeInfo *crtc_mode_info);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaCrtcModeInfo, meta_crtc_mode_info_unref)
uint64_t meta_crtc_mode_get_id (MetaCrtcMode *crtc_mode);
const char * meta_crtc_mode_get_name (MetaCrtcMode *crtc_mode);
META_EXPORT_TEST
const MetaCrtcModeInfo * meta_crtc_mode_get_info (MetaCrtcMode *crtc_mode);
#endif /* META_CRTC_MODE_H */

View File

@@ -21,14 +21,56 @@
#include "backends/meta-crtc.h"
G_DEFINE_TYPE (MetaCrtc, meta_crtc, G_TYPE_OBJECT)
#include "backends/meta-gpu.h"
G_DEFINE_TYPE (MetaCrtcMode, meta_crtc_mode, G_TYPE_OBJECT)
enum
{
PROP_0,
PROP_ID,
PROP_GPU,
PROP_ALL_TRANSFORMS,
N_PROPS
};
static GParamSpec *obj_props[N_PROPS];
typedef struct _MetaCrtcPrivate
{
uint64_t id;
MetaGpu *gpu;
MetaMonitorTransform all_transforms;
MetaCrtcConfig *config;
} MetaCrtcPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCrtc, meta_crtc, G_TYPE_OBJECT)
uint64_t
meta_crtc_get_id (MetaCrtc *crtc)
{
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
return priv->id;
}
MetaGpu *
meta_crtc_get_gpu (MetaCrtc *crtc)
{
return crtc->gpu;
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
return priv->gpu;
}
MetaMonitorTransform
meta_crtc_get_all_transforms (MetaCrtc *crtc)
{
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
return priv->all_transforms;
}
void
@@ -37,6 +79,7 @@ meta_crtc_set_config (MetaCrtc *crtc,
MetaCrtcMode *mode,
MetaMonitorTransform transform)
{
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
MetaCrtcConfig *config;
meta_crtc_unset_config (crtc);
@@ -46,24 +89,82 @@ meta_crtc_set_config (MetaCrtc *crtc,
config->mode = mode;
config->transform = transform;
crtc->config = config;
priv->config = config;
}
void
meta_crtc_unset_config (MetaCrtc *crtc)
{
g_clear_pointer (&crtc->config, g_free);
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
g_clear_pointer (&priv->config, g_free);
}
const MetaCrtcConfig *
meta_crtc_get_config (MetaCrtc *crtc)
{
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
return priv->config;
}
static void
meta_crtc_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaCrtc *crtc = META_CRTC (object);
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
switch (prop_id)
{
case PROP_ID:
priv->id = g_value_get_uint64 (value);
break;
case PROP_GPU:
priv->gpu = g_value_get_object (value);
break;
case PROP_ALL_TRANSFORMS:
priv->all_transforms = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_crtc_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaCrtc *crtc = META_CRTC (object);
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
switch (prop_id)
{
case PROP_ID:
g_value_set_uint64 (value, priv->id);
break;
case PROP_GPU:
g_value_set_object (value, priv->gpu);
break;
case PROP_ALL_TRANSFORMS:
g_value_set_uint (value, priv->all_transforms);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_crtc_finalize (GObject *object)
{
MetaCrtc *crtc = META_CRTC (object);
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
if (crtc->driver_notify)
crtc->driver_notify (crtc);
g_clear_pointer (&crtc->config, g_free);
g_clear_pointer (&priv->config, g_free);
G_OBJECT_CLASS (meta_crtc_parent_class)->finalize (object);
}
@@ -71,6 +172,9 @@ meta_crtc_finalize (GObject *object)
static void
meta_crtc_init (MetaCrtc *crtc)
{
MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
priv->all_transforms = META_MONITOR_ALL_TRANSFORMS;
}
static void
@@ -78,31 +182,35 @@ meta_crtc_class_init (MetaCrtcClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = meta_crtc_set_property;
object_class->get_property = meta_crtc_get_property;
object_class->finalize = meta_crtc_finalize;
}
static void
meta_crtc_mode_finalize (GObject *object)
{
MetaCrtcMode *crtc_mode = META_CRTC_MODE (object);
if (crtc_mode->driver_notify)
crtc_mode->driver_notify (crtc_mode);
g_clear_pointer (&crtc_mode->name, g_free);
G_OBJECT_CLASS (meta_crtc_mode_parent_class)->finalize (object);
}
static void
meta_crtc_mode_init (MetaCrtcMode *crtc_mode)
{
}
static void
meta_crtc_mode_class_init (MetaCrtcModeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_crtc_mode_finalize;
obj_props[PROP_ID] =
g_param_spec_uint64 ("id",
"id",
"CRTC id",
0, UINT64_MAX, 0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_GPU] =
g_param_spec_object ("gpu",
"gpu",
"MetaGpu",
META_TYPE_GPU,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_ALL_TRANSFORMS] =
g_param_spec_uint ("all-transforms",
"all-transforms",
"All transforms",
0,
META_MONITOR_ALL_TRANSFORMS,
META_MONITOR_ALL_TRANSFORMS,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, obj_props);
}

View File

@@ -23,32 +23,11 @@
#include <glib-object.h>
#include "backends/meta-backend-types.h"
#include "backends/meta-crtc-mode.h"
#include "backends/meta-monitor-transform.h"
#include "core/util-private.h"
#include "meta/boxes.h"
/* Same as KMS mode flags and X11 randr flags */
typedef enum _MetaCrtcModeFlag
{
META_CRTC_MODE_FLAG_NONE = 0,
META_CRTC_MODE_FLAG_PHSYNC = (1 << 0),
META_CRTC_MODE_FLAG_NHSYNC = (1 << 1),
META_CRTC_MODE_FLAG_PVSYNC = (1 << 2),
META_CRTC_MODE_FLAG_NVSYNC = (1 << 3),
META_CRTC_MODE_FLAG_INTERLACE = (1 << 4),
META_CRTC_MODE_FLAG_DBLSCAN = (1 << 5),
META_CRTC_MODE_FLAG_CSYNC = (1 << 6),
META_CRTC_MODE_FLAG_PCSYNC = (1 << 7),
META_CRTC_MODE_FLAG_NCSYNC = (1 << 8),
META_CRTC_MODE_FLAG_HSKEW = (1 << 9),
META_CRTC_MODE_FLAG_BCAST = (1 << 10),
META_CRTC_MODE_FLAG_PIXMUX = (1 << 11),
META_CRTC_MODE_FLAG_DBLCLK = (1 << 12),
META_CRTC_MODE_FLAG_CLKDIV2 = (1 << 13),
META_CRTC_MODE_FLAG_MASK = 0x3fff
} MetaCrtcModeFlag;
typedef struct _MetaCrtcConfig
{
graphene_rect_t layout;
@@ -56,52 +35,23 @@ typedef struct _MetaCrtcConfig
MetaCrtcMode *mode;
} MetaCrtcConfig;
struct _MetaCrtc
{
GObject parent;
MetaGpu *gpu;
glong crtc_id;
unsigned int all_transforms;
MetaCrtcConfig *config;
/* Used when changing configuration */
gboolean is_dirty;
/* Used by cursor renderer backend */
void *cursor_renderer_private;
gpointer driver_private;
GDestroyNotify driver_notify;
};
struct _MetaCrtcMode
{
GObject parent;
/* The low-level ID of this mode, used to apply back configuration */
glong mode_id;
char *name;
int width;
int height;
float refresh_rate;
MetaCrtcModeFlag flags;
gpointer driver_private;
GDestroyNotify driver_notify;
};
#define META_TYPE_CRTC (meta_crtc_get_type ())
META_EXPORT_TEST G_DECLARE_FINAL_TYPE (MetaCrtc, meta_crtc, META, CRTC, GObject)
META_EXPORT_TEST
G_DECLARE_DERIVABLE_TYPE (MetaCrtc, meta_crtc, META, CRTC, GObject)
#define META_TYPE_CRTC_MODE (meta_crtc_mode_get_type ())
META_EXPORT_TEST G_DECLARE_FINAL_TYPE (MetaCrtcMode, meta_crtc_mode, META, CRTC_MODE, GObject)
struct _MetaCrtcClass
{
GObjectClass parent_class;
};
META_EXPORT_TEST
uint64_t meta_crtc_get_id (MetaCrtc *crtc);
META_EXPORT_TEST
MetaGpu * meta_crtc_get_gpu (MetaCrtc *crtc);
MetaMonitorTransform meta_crtc_get_all_transforms (MetaCrtc *crtc);
META_EXPORT_TEST
void meta_crtc_set_config (MetaCrtc *crtc,
graphene_rect_t *layout,
@@ -111,4 +61,7 @@ void meta_crtc_set_config (MetaCrtc *crtc,
META_EXPORT_TEST
void meta_crtc_unset_config (MetaCrtc *crtc);
META_EXPORT_TEST
const MetaCrtcConfig * meta_crtc_get_config (MetaCrtc *crtc);
#endif /* META_CRTC_H */

View File

@@ -38,8 +38,21 @@
G_DEFINE_INTERFACE (MetaHwCursorInhibitor, meta_hw_cursor_inhibitor,
G_TYPE_OBJECT)
enum
{
PROP_0,
PROP_BACKEND,
N_PROPS
};
static GParamSpec *obj_props[N_PROPS];
struct _MetaCursorRendererPrivate
{
MetaBackend *backend;
float current_x;
float current_y;
@@ -89,8 +102,7 @@ align_cursor_position (MetaCursorRenderer *renderer,
{
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
ClutterActor *stage = meta_backend_get_stage (priv->backend);
ClutterStageView *view;
cairo_rectangle_int_t view_layout;
float view_scale;
@@ -115,8 +127,7 @@ queue_redraw (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
ClutterActor *stage = meta_backend_get_stage (priv->backend);
CoglTexture *texture;
graphene_rect_t rect = GRAPHENE_RECT_INIT_ZERO;
@@ -165,13 +176,54 @@ meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer,
return FALSE;
}
static void
meta_cursor_renderer_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object);
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
switch (prop_id)
{
case PROP_BACKEND:
g_value_set_object (value, priv->backend);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_cursor_renderer_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object);
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
switch (prop_id)
{
case PROP_BACKEND:
priv->backend = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_cursor_renderer_finalize (GObject *object)
{
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object);
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
ClutterActor *stage = meta_backend_get_stage (priv->backend);
if (priv->stage_overlay)
meta_stage_remove_cursor_overlay (META_STAGE (stage), priv->stage_overlay);
@@ -186,9 +238,21 @@ meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = meta_cursor_renderer_get_property;
object_class->set_property = meta_cursor_renderer_set_property;
object_class->finalize = meta_cursor_renderer_finalize;
klass->update_cursor = meta_cursor_renderer_real_update_cursor;
obj_props[PROP_BACKEND] =
g_param_spec_object ("backend",
"backend",
"MetaBackend",
META_TYPE_BACKEND,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, obj_props);
signals[CURSOR_PAINTED] = g_signal_new ("cursor-painted",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
@@ -273,9 +337,11 @@ meta_cursor_renderer_update_cursor (MetaCursorRenderer *renderer,
}
MetaCursorRenderer *
meta_cursor_renderer_new (void)
meta_cursor_renderer_new (MetaBackend *backend)
{
return g_object_new (META_TYPE_CURSOR_RENDERER, NULL);
return g_object_new (META_TYPE_CURSOR_RENDERER,
"backend", backend,
NULL);
}
void

View File

@@ -54,7 +54,7 @@ struct _MetaCursorRendererClass
MetaCursorSprite *cursor_sprite);
};
MetaCursorRenderer * meta_cursor_renderer_new (void);
MetaCursorRenderer * meta_cursor_renderer_new (MetaBackend *backend);
void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite);

View File

@@ -57,8 +57,9 @@ meta_gpu_has_hotplug_mode_update (MetaGpu *gpu)
for (l = priv->outputs; l; l = l->next)
{
MetaOutput *output = l->data;
const MetaOutputInfo *output_info = meta_output_get_info (output);
if (output->hotplug_mode_update)
if (output_info->hotplug_mode_update)
return TRUE;
}

View File

@@ -0,0 +1,56 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Utilities for use with libxkbcommon
*
* Copyright 2019 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "backends/meta-keymap-utils.h"
#include <glib.h>
#include <limits.h>
struct xkb_context *
meta_create_xkb_context (void)
{
struct xkb_context *ctx;
char xdg[PATH_MAX] = {0};
const char *env;
/*
* We can only append search paths in libxkbcommon, so we start with an
* emtpy set, then add the XDG dir, then add the default search paths.
*/
ctx = xkb_context_new (XKB_CONTEXT_NO_DEFAULT_INCLUDES);
env = g_getenv ("XDG_CONFIG_HOME");
if (env)
{
g_snprintf (xdg, sizeof xdg, "%s/xkb", env);
}
else if ((env = g_getenv ("HOME")))
{
g_snprintf (xdg, sizeof xdg, "%s/.config/xkb", env);
}
if (env)
xkb_context_include_path_append (ctx, xdg);
xkb_context_include_path_append_default (ctx);
return ctx;
}

View File

@@ -0,0 +1,28 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Utilities for use with libxkbcommon
*
* Copyright 2020 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_KEYMAP_UTILS_H
#define META_KEYMAP_UTILS_H
#include <xkbcommon/xkbcommon.h>
struct xkb_context * meta_create_xkb_context (void);
#endif /* META_KEYMAP_UTILS_H */

View File

@@ -99,7 +99,7 @@ meta_logical_monitor_new (MetaMonitorManager *monitor_manager,
main_output = meta_monitor_get_main_output (first_monitor);
logical_monitor->number = monitor_number;
logical_monitor->winsys_id = main_output->winsys_id;
logical_monitor->winsys_id = meta_output_get_id (main_output);
logical_monitor->scale = logical_monitor_config->scale;
logical_monitor->transform = logical_monitor_config->transform;
logical_monitor->in_fullscreen = -1;
@@ -119,10 +119,14 @@ static MetaMonitorTransform
derive_monitor_transform (MetaMonitor *monitor)
{
MetaOutput *main_output;
MetaCrtc *crtc;
const MetaCrtcConfig *crtc_config;
MetaMonitorTransform transform;
main_output = meta_monitor_get_main_output (monitor);
transform = meta_output_get_assigned_crtc (main_output)->config->transform;
crtc = meta_output_get_assigned_crtc (main_output);
crtc_config = meta_crtc_get_config (crtc);
transform = crtc_config->transform;
return meta_monitor_crtc_to_logical_transform (monitor, transform);
}
@@ -144,7 +148,7 @@ meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager,
main_output = meta_monitor_get_main_output (monitor);
logical_monitor->number = monitor_number;
logical_monitor->winsys_id = main_output->winsys_id;
logical_monitor->winsys_id = meta_output_get_id (main_output);
logical_monitor->scale = scale;
logical_monitor->transform = transform;
logical_monitor->in_fullscreen = -1;
@@ -178,7 +182,8 @@ meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
{
MetaOutput *output = l_output->data;
is_presentation = is_presentation && output->is_presentation;
is_presentation = (is_presentation &&
meta_output_is_presentation (output));
}
}

View File

@@ -52,10 +52,10 @@ G_DEFINE_TYPE (MetaMonitorsConfig, meta_monitors_config,
G_TYPE_OBJECT)
static void
meta_crtc_info_free (MetaCrtcInfo *info);
meta_crtc_assignment_free (MetaCrtcAssignment *assignment);
static void
meta_output_info_free (MetaOutputInfo *info);
meta_output_assignment_free (MetaOutputAssignment *assignment);
MetaMonitorConfigManager *
meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager)
@@ -84,8 +84,10 @@ is_crtc_reserved (MetaCrtc *crtc,
for (i = 0; i < reserved_crtcs->len; i++)
{
glong id = g_array_index (reserved_crtcs, glong, i);
if (id == crtc->crtc_id)
uint64_t id;
id = g_array_index (reserved_crtcs, uint64_t, i);
if (id == meta_crtc_get_id (crtc))
return TRUE;
}
@@ -94,15 +96,16 @@ is_crtc_reserved (MetaCrtc *crtc,
static gboolean
is_crtc_assigned (MetaCrtc *crtc,
GPtrArray *crtc_infos)
GPtrArray *crtc_assignments)
{
unsigned int i;
for (i = 0; i < crtc_infos->len; i++)
for (i = 0; i < crtc_assignments->len; i++)
{
MetaCrtcInfo *assigned_crtc_info = g_ptr_array_index (crtc_infos, i);
MetaCrtcAssignment *assigned_crtc_assignment =
g_ptr_array_index (crtc_assignments, i);
if (assigned_crtc_info->crtc == crtc)
if (assigned_crtc_assignment->crtc == crtc)
return TRUE;
}
@@ -111,22 +114,25 @@ is_crtc_assigned (MetaCrtc *crtc,
static MetaCrtc *
find_unassigned_crtc (MetaOutput *output,
GPtrArray *crtc_infos,
GPtrArray *crtc_assignments,
GArray *reserved_crtcs)
{
MetaCrtc *crtc;
const MetaOutputInfo *output_info;
unsigned int i;
crtc = meta_output_get_assigned_crtc (output);
if (crtc && !is_crtc_assigned (crtc, crtc_infos))
if (crtc && !is_crtc_assigned (crtc, crtc_assignments))
return crtc;
/* then try to assign a CRTC that wasn't used */
for (i = 0; i < output->n_possible_crtcs; i++)
{
crtc = output->possible_crtcs[i];
output_info = meta_output_get_info (output);
if (is_crtc_assigned (crtc, crtc_infos))
/* then try to assign a CRTC that wasn't used */
for (i = 0; i < output_info->n_possible_crtcs; i++)
{
crtc = output_info->possible_crtcs[i];
if (is_crtc_assigned (crtc, crtc_assignments))
continue;
if (is_crtc_reserved (crtc, reserved_crtcs))
@@ -136,11 +142,11 @@ find_unassigned_crtc (MetaOutput *output,
}
/* finally just give a CRTC that we haven't assigned */
for (i = 0; i < output->n_possible_crtcs; i++)
for (i = 0; i < output_info->n_possible_crtcs; i++)
{
crtc = output->possible_crtcs[i];
crtc = output_info->possible_crtcs[i];
if (is_crtc_assigned (crtc, crtc_infos))
if (is_crtc_assigned (crtc, crtc_assignments))
continue;
return crtc;
@@ -155,8 +161,8 @@ typedef struct
MetaMonitorsConfig *config;
MetaLogicalMonitorConfig *logical_monitor_config;
MetaMonitorConfig *monitor_config;
GPtrArray *crtc_infos;
GPtrArray *output_infos;
GPtrArray *crtc_assignments;
GPtrArray *output_assignments;
GArray *reserved_crtcs;
} MonitorAssignmentData;
@@ -178,16 +184,19 @@ assign_monitor_crtc (MetaMonitor *monitor,
float scale = 0.0;
float width, height;
MetaCrtcMode *crtc_mode;
const MetaCrtcModeInfo *crtc_mode_info;
graphene_rect_t crtc_layout;
MetaCrtcInfo *crtc_info;
MetaOutputInfo *output_info;
MetaCrtcAssignment *crtc_assignment;
MetaOutputAssignment *output_assignment;
MetaMonitorConfig *first_monitor_config;
gboolean assign_output_as_primary;
gboolean assign_output_as_presentation;
output = monitor_crtc_mode->output;
crtc = find_unassigned_crtc (output, data->crtc_infos, data->reserved_crtcs);
crtc = find_unassigned_crtc (output,
data->crtc_assignments,
data->reserved_crtcs);
if (!crtc)
{
@@ -225,16 +234,17 @@ assign_monitor_crtc (MetaMonitor *monitor,
}
crtc_mode = monitor_crtc_mode->crtc_mode;
crtc_mode_info = meta_crtc_mode_get_info (monitor_crtc_mode->crtc_mode);
if (meta_monitor_transform_is_rotated (crtc_transform))
{
width = crtc_mode->height / scale;
height = crtc_mode->width / scale;
width = crtc_mode_info->height / scale;
height = crtc_mode_info->width / scale;
}
else
{
width = crtc_mode->width / scale;
height = crtc_mode->height / scale;
width = crtc_mode_info->width / scale;
height = crtc_mode_info->height / scale;
}
crtc_layout = GRAPHENE_RECT_INIT (x_offset + (crtc_x / scale),
@@ -242,15 +252,15 @@ assign_monitor_crtc (MetaMonitor *monitor,
width,
height);
crtc_info = g_slice_new0 (MetaCrtcInfo);
*crtc_info = (MetaCrtcInfo) {
crtc_assignment = g_slice_new0 (MetaCrtcAssignment);
*crtc_assignment = (MetaCrtcAssignment) {
.crtc = crtc,
.mode = crtc_mode,
.layout = crtc_layout,
.transform = crtc_hw_transform,
.outputs = g_ptr_array_new ()
};
g_ptr_array_add (crtc_info->outputs, output);
g_ptr_array_add (crtc_assignment->outputs, output);
/*
* Only one output can be marked as primary (due to Xrandr limitation),
@@ -270,16 +280,16 @@ assign_monitor_crtc (MetaMonitor *monitor,
else
assign_output_as_presentation = FALSE;
output_info = g_slice_new0 (MetaOutputInfo);
*output_info = (MetaOutputInfo) {
output_assignment = g_slice_new0 (MetaOutputAssignment);
*output_assignment = (MetaOutputAssignment) {
.output = output,
.is_primary = assign_output_as_primary,
.is_presentation = assign_output_as_presentation,
.is_underscanning = data->monitor_config->enable_underscanning
};
g_ptr_array_add (data->crtc_infos, crtc_info);
g_ptr_array_add (data->output_infos, output_info);
g_ptr_array_add (data->crtc_assignments, crtc_assignment);
g_ptr_array_add (data->output_assignments, output_assignment);
return TRUE;
}
@@ -289,8 +299,8 @@ assign_monitor_crtcs (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
MetaLogicalMonitorConfig *logical_monitor_config,
MetaMonitorConfig *monitor_config,
GPtrArray *crtc_infos,
GPtrArray *output_infos,
GPtrArray *crtc_assignments,
GPtrArray *output_assignments,
GArray *reserved_crtcs,
GError **error)
{
@@ -325,8 +335,8 @@ assign_monitor_crtcs (MetaMonitorManager *manager,
.config = config,
.logical_monitor_config = logical_monitor_config,
.monitor_config = monitor_config,
.crtc_infos = crtc_infos,
.output_infos = output_infos,
.crtc_assignments = crtc_assignments,
.output_assignments = output_assignments,
.reserved_crtcs = reserved_crtcs
};
if (!meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
@@ -342,8 +352,8 @@ static gboolean
assign_logical_monitor_crtcs (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
MetaLogicalMonitorConfig *logical_monitor_config,
GPtrArray *crtc_infos,
GPtrArray *output_infos,
GPtrArray *crtc_assignments,
GPtrArray *output_assignments,
GArray *reserved_crtcs,
GError **error)
{
@@ -357,7 +367,7 @@ assign_logical_monitor_crtcs (MetaMonitorManager *manager,
config,
logical_monitor_config,
monitor_config,
crtc_infos, output_infos,
crtc_assignments, output_assignments,
reserved_crtcs, error))
return FALSE;
}
@@ -368,20 +378,20 @@ assign_logical_monitor_crtcs (MetaMonitorManager *manager,
gboolean
meta_monitor_config_manager_assign (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
GPtrArray **out_crtc_infos,
GPtrArray **out_output_infos,
GPtrArray **out_crtc_assignments,
GPtrArray **out_output_assignments,
GError **error)
{
GPtrArray *crtc_infos;
GPtrArray *output_infos;
GPtrArray *crtc_assignments;
GPtrArray *output_assignments;
GArray *reserved_crtcs;
GList *l;
crtc_infos =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_crtc_info_free);
output_infos =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_output_info_free);
reserved_crtcs = g_array_new (FALSE, FALSE, sizeof (glong));
crtc_assignments =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_crtc_assignment_free);
output_assignments =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_output_assignment_free);
reserved_crtcs = g_array_new (FALSE, FALSE, sizeof (uint64_t));
for (l = config->logical_monitor_configs; l; l = l->next)
{
@@ -404,7 +414,11 @@ meta_monitor_config_manager_assign (MetaMonitorManager *manager,
crtc = meta_output_get_assigned_crtc (output);
if (crtc)
g_array_append_val (reserved_crtcs, crtc->crtc_id);
{
uint64_t crtc_id = meta_crtc_get_id (crtc);
g_array_append_val (reserved_crtcs, crtc_id);
}
}
}
}
@@ -415,11 +429,11 @@ meta_monitor_config_manager_assign (MetaMonitorManager *manager,
if (!assign_logical_monitor_crtcs (manager,
config, logical_monitor_config,
crtc_infos, output_infos,
crtc_assignments, output_assignments,
reserved_crtcs, error))
{
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
g_ptr_array_free (crtc_assignments, TRUE);
g_ptr_array_free (output_assignments, TRUE);
g_array_free (reserved_crtcs, TRUE);
return FALSE;
}
@@ -427,8 +441,8 @@ meta_monitor_config_manager_assign (MetaMonitorManager *manager,
g_array_free (reserved_crtcs, TRUE);
*out_crtc_infos = crtc_infos;
*out_output_infos = output_infos;
*out_crtc_assignments = crtc_assignments;
*out_output_assignments = output_assignments;
return TRUE;
}
@@ -1557,16 +1571,16 @@ meta_monitors_config_class_init (MetaMonitorsConfigClass *klass)
}
static void
meta_crtc_info_free (MetaCrtcInfo *info)
meta_crtc_assignment_free (MetaCrtcAssignment *assignment)
{
g_ptr_array_free (info->outputs, TRUE);
g_slice_free (MetaCrtcInfo, info);
g_ptr_array_free (assignment->outputs, TRUE);
g_slice_free (MetaCrtcAssignment, assignment);
}
static void
meta_output_info_free (MetaOutputInfo *info)
meta_output_assignment_free (MetaOutputAssignment *assignment)
{
g_slice_free (MetaOutputInfo, info);
g_slice_free (MetaOutputAssignment, assignment);
}
gboolean

View File

@@ -87,8 +87,8 @@ MetaMonitorConfigStore * meta_monitor_config_manager_get_store (MetaMonitorConfi
META_EXPORT_TEST
gboolean meta_monitor_config_manager_assign (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
GPtrArray **crtc_infos,
GPtrArray **output_infos,
GPtrArray **crtc_assignments,
GPtrArray **output_assignments,
GError **error);
META_EXPORT_TEST

View File

@@ -36,8 +36,6 @@
#include "backends/meta-output.h"
#include "meta/util.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
#define MAX_MONITORS 5
#define MAX_OUTPUTS (MAX_MONITORS * 2)
#define MAX_CRTCS (MAX_MONITORS * 2)
@@ -55,11 +53,20 @@ struct _MetaMonitorManagerDummyClass
MetaMonitorManagerClass parent_class;
};
typedef struct _MetaOutputDummy
struct _MetaOutputDummy
{
float scale;
} MetaOutputDummy;
MetaOutput parent;
float scale;
};
struct _MetaCrtcDummy
{
MetaCrtc parent;
};
G_DEFINE_TYPE (MetaOutputDummy, meta_output_dummy, META_TYPE_OUTPUT)
G_DEFINE_TYPE (MetaCrtcDummy, meta_crtc_dummy, META_TYPE_CRTC)
G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MONITOR_MANAGER);
struct _MetaGpuDummy
@@ -69,9 +76,6 @@ struct _MetaGpuDummy
G_DEFINE_TYPE (MetaGpuDummy, meta_gpu_dummy, META_TYPE_GPU)
static void
meta_output_dummy_notify_destroy (MetaOutput *output);
typedef struct _CrtcModeSpec
{
int width;
@@ -84,16 +88,17 @@ static MetaCrtcMode *
create_mode (CrtcModeSpec *spec,
long mode_id)
{
MetaCrtcMode *mode;
g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL;
mode = g_object_new (META_TYPE_CRTC_MODE, NULL);
crtc_mode_info = meta_crtc_mode_info_new ();
crtc_mode_info->width = spec->width;
crtc_mode_info->height = spec->height;
crtc_mode_info->refresh_rate = spec->refresh_rate;
mode->mode_id = mode_id;
mode->width = spec->width;
mode->height = spec->height;
mode->refresh_rate = spec->refresh_rate;
return mode;
return g_object_new (META_TYPE_CRTC_MODE,
"id", mode_id,
"info", crtc_mode_info,
NULL);
}
static MetaGpu *
@@ -142,6 +147,7 @@ append_monitor (MetaMonitorManager *manager,
MetaOutput *output;
unsigned int i;
unsigned int number;
g_autoptr (MetaOutputInfo) output_info = NULL;
const char *mode_specs_str;
GList *l;
@@ -198,50 +204,45 @@ append_monitor (MetaMonitorManager *manager,
}
*modes = g_list_concat (*modes, new_modes);
crtc = g_object_new (META_TYPE_CRTC, NULL);
crtc->crtc_id = g_list_length (*crtcs) + 1;
crtc->all_transforms = ALL_TRANSFORMS;
crtc = g_object_new (META_TYPE_CRTC_DUMMY,
"id", g_list_length (*crtcs) + 1,
"gpu", gpu,
NULL);
*crtcs = g_list_append (*crtcs, crtc);
output = g_object_new (META_TYPE_OUTPUT, NULL);
output_dummy = g_new0 (MetaOutputDummy, 1);
*output_dummy = (MetaOutputDummy) {
.scale = scale
};
number = g_list_length (*outputs) + 1;
output->gpu = gpu;
output->winsys_id = number;
output->name = g_strdup_printf ("LVDS%d", number);
output->vendor = g_strdup ("MetaProducts Inc.");
output->product = g_strdup ("MetaMonitor");
output->serial = g_strdup_printf ("0xC0FFEE-%d", number);
output->suggested_x = -1;
output->suggested_y = -1;
output->width_mm = 222;
output->height_mm = 125;
output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
output->preferred_mode = g_list_last (*modes)->data;
output->n_possible_clones = 0;
output->backlight = -1;
output->connector_type = META_CONNECTOR_TYPE_LVDS;
output->driver_private = output_dummy;
output->driver_notify =
(GDestroyNotify) meta_output_dummy_notify_destroy;
output_info = meta_output_info_new ();
output_info->name = g_strdup_printf ("LVDS%d", number);
output_info->vendor = g_strdup ("MetaProducts Inc.");
output_info->product = g_strdup ("MetaMonitor");
output_info->serial = g_strdup_printf ("0xC0FFEE-%d", number);
output_info->width_mm = 222;
output_info->height_mm = 125;
output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
output_info->preferred_mode = g_list_last (*modes)->data;
output_info->n_possible_clones = 0;
output_info->connector_type = META_CONNECTOR_TYPE_LVDS;
output->modes = g_new0 (MetaCrtcMode *, n_mode_specs);
output_info->modes = g_new0 (MetaCrtcMode *, n_mode_specs);
for (l = new_modes, i = 0; l; l = l->next, i++)
{
MetaCrtcMode *mode = l->data;
output->modes[i] = mode;
output_info->modes[i] = mode;
}
output->n_modes = n_mode_specs;
output->possible_crtcs = g_new0 (MetaCrtc *, 1);
output->possible_crtcs[0] = g_list_last (*crtcs)->data;
output->n_possible_crtcs = 1;
output_info->n_modes = n_mode_specs;
output_info->possible_crtcs = g_new0 (MetaCrtc *, 1);
output_info->possible_crtcs[0] = g_list_last (*crtcs)->data;
output_info->n_possible_crtcs = 1;
output = g_object_new (META_TYPE_OUTPUT_DUMMY,
"id", number,
"gpu", gpu,
"info", output_info,
NULL);
output_dummy = META_OUTPUT_DUMMY (output);
output_dummy->scale = scale;
*outputs = g_list_append (*outputs, output);
}
@@ -289,10 +290,10 @@ append_tiled_monitor (MetaMonitorManager *manager,
{
MetaCrtc *crtc;
crtc = g_object_new (META_TYPE_CRTC, NULL);
crtc->gpu = gpu;
crtc->crtc_id = g_list_length (*crtcs) + i + 1;
crtc->all_transforms = ALL_TRANSFORMS;
crtc = g_object_new (META_TYPE_CRTC_DUMMY,
"id", g_list_length (*crtcs) + i + 1,
"gpu", gpu,
NULL);
new_crtcs = g_list_append (new_crtcs, crtc);
}
*crtcs = g_list_concat (*crtcs, new_crtcs);
@@ -302,78 +303,72 @@ append_tiled_monitor (MetaMonitorManager *manager,
{
MetaOutputDummy *output_dummy;
MetaCrtcMode *preferred_mode;
const MetaCrtcModeInfo *preferred_mode_info;
unsigned int j;
unsigned int number;
g_autoptr (MetaOutputInfo) output_info = NULL;
GList *l;
output_dummy = g_new0 (MetaOutputDummy, 1);
*output_dummy = (MetaOutputDummy) {
.scale = scale
};
/* Arbitrary ID unique for this output */
number = g_list_length (*outputs) + 1;
preferred_mode = g_list_last (*modes)->data;
preferred_mode_info = meta_crtc_mode_get_info (preferred_mode);
output = g_object_new (META_TYPE_OUTPUT, NULL);
output_info = meta_output_info_new ();
output->gpu = gpu;
output->winsys_id = number;
output->name = g_strdup_printf ("LVDS%d", number);
output->vendor = g_strdup ("MetaProducts Inc.");
output->product = g_strdup ("MetaMonitor");
output->serial = g_strdup_printf ("0xC0FFEE-%d", number);
output->suggested_x = -1;
output->suggested_y = -1;
output->width_mm = 222;
output->height_mm = 125;
output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
output->preferred_mode = preferred_mode;
output->n_possible_clones = 0;
output->backlight = -1;
output->connector_type = META_CONNECTOR_TYPE_LVDS;
output->tile_info = (MetaTileInfo) {
output_info->name = g_strdup_printf ("LVDS%d", number);
output_info->vendor = g_strdup ("MetaProducts Inc.");
output_info->product = g_strdup ("MetaMonitor");
output_info->serial = g_strdup_printf ("0xC0FFEE-%d", number);
output_info->suggested_x = -1;
output_info->suggested_y = -1;
output_info->width_mm = 222;
output_info->height_mm = 125;
output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
output_info->preferred_mode = preferred_mode;
output_info->n_possible_clones = 0;
output_info->connector_type = META_CONNECTOR_TYPE_LVDS;
output_info->tile_info = (MetaTileInfo) {
.group_id = tile_group_id,
.max_h_tiles = n_tiles,
.max_v_tiles = 1,
.loc_h_tile = i,
.loc_v_tile = 0,
.tile_w = preferred_mode->width,
.tile_h = preferred_mode->height
.tile_w = preferred_mode_info->width,
.tile_h = preferred_mode_info->height
},
output->driver_private = output_dummy;
output->driver_notify =
(GDestroyNotify) meta_output_dummy_notify_destroy;
output->modes = g_new0 (MetaCrtcMode *, G_N_ELEMENTS (mode_specs));
output_info->modes = g_new0 (MetaCrtcMode *, G_N_ELEMENTS (mode_specs));
for (l = new_modes, j = 0; l; l = l->next, j++)
{
MetaCrtcMode *mode = l->data;
output->modes[j] = mode;
output_info->modes[j] = mode;
}
output->n_modes = G_N_ELEMENTS (mode_specs);
output_info->n_modes = G_N_ELEMENTS (mode_specs);
output->possible_crtcs = g_new0 (MetaCrtc *, n_tiles);
output_info->possible_crtcs = g_new0 (MetaCrtc *, n_tiles);
for (l = new_crtcs, j = 0; l; l = l->next, j++)
{
MetaCrtc *crtc = l->data;
output->possible_crtcs[j] = crtc;
output_info->possible_crtcs[j] = crtc;
}
output->n_possible_crtcs = n_tiles;
output_info->n_possible_crtcs = n_tiles;
output = g_object_new (META_TYPE_OUTPUT_DUMMY,
"id", number,
"gpu", gpu,
"info", output_info,
NULL);
output_dummy = META_OUTPUT_DUMMY (output);
output_dummy->scale = scale;
*outputs = g_list_append (*outputs, output);
}
}
static void
meta_output_dummy_notify_destroy (MetaOutput *output)
{
g_clear_pointer (&output->driver_private, g_free);
}
static void
meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
{
@@ -495,82 +490,63 @@ meta_monitor_manager_dummy_ensure_initial_config (MetaMonitorManager *manager)
}
static void
apply_crtc_assignments (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
apply_crtc_assignments (MetaMonitorManager *manager,
MetaCrtcAssignment **crtcs,
unsigned int n_crtcs,
MetaOutputAssignment **outputs,
unsigned int n_outputs)
{
GList *l;
g_autoptr (GList) to_configure_outputs = NULL;
g_autoptr (GList) to_configure_crtcs = NULL;
unsigned i;
to_configure_outputs = g_list_copy (meta_gpu_get_outputs (get_gpu (manager)));
to_configure_crtcs = g_list_copy (meta_gpu_get_crtcs (get_gpu (manager)));
for (i = 0; i < n_crtcs; i++)
{
MetaCrtcInfo *crtc_info = crtcs[i];
MetaCrtc *crtc = crtc_info->crtc;
crtc->is_dirty = TRUE;
MetaCrtcAssignment *crtc_assignment = crtcs[i];
MetaCrtc *crtc = crtc_assignment->crtc;
if (crtc_info->mode == NULL)
to_configure_crtcs = g_list_remove (to_configure_crtcs, crtc);
if (crtc_assignment->mode == NULL)
{
meta_crtc_unset_config (crtc);
}
else
{
MetaOutput *output;
unsigned int j;
meta_crtc_set_config (crtc,
&crtc_info->layout,
crtc_info->mode,
crtc_info->transform);
&crtc_assignment->layout,
crtc_assignment->mode,
crtc_assignment->transform);
for (j = 0; j < crtc_info->outputs->len; j++)
for (j = 0; j < crtc_assignment->outputs->len; j++)
{
output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
MetaOutput *output;
MetaOutputAssignment *output_assignment;
output->is_dirty = TRUE;
meta_output_assign_crtc (output, crtc);
output = ((MetaOutput**) crtc_assignment->outputs->pdata)[j];
to_configure_outputs = g_list_remove (to_configure_outputs,
output);
output_assignment = meta_find_output_assignment (outputs,
n_outputs,
output);
meta_output_assign_crtc (output, crtc, output_assignment);
}
}
}
for (i = 0; i < n_outputs; i++)
{
MetaOutputInfo *output_info = outputs[i];
MetaOutput *output = output_info->output;
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
}
/* Disable CRTCs not mentioned in the list */
for (l = meta_gpu_get_crtcs (get_gpu (manager)); l; l = l->next)
{
MetaCrtc *crtc = l->data;
if (crtc->is_dirty)
{
crtc->is_dirty = FALSE;
continue;
}
meta_crtc_unset_config (crtc);
}
/* Disable outputs not mentioned in the list */
for (l = meta_gpu_get_outputs (get_gpu (manager)); l; l = l->next)
{
MetaOutput *output = l->data;
if (output->is_dirty)
{
output->is_dirty = FALSE;
continue;
}
meta_output_unassign_crtc (output);
output->is_primary = FALSE;
}
g_list_foreach (to_configure_crtcs,
(GFunc) meta_crtc_unset_config,
NULL);
g_list_foreach (to_configure_outputs,
(GFunc) meta_output_unassign_crtc,
NULL);
}
static void
@@ -608,8 +584,8 @@ meta_monitor_manager_dummy_apply_monitors_config (MetaMonitorManager *manag
MetaMonitorsConfigMethod method,
GError **error)
{
GPtrArray *crtc_infos;
GPtrArray *output_infos;
GPtrArray *crtc_assignments;
GPtrArray *output_assignments;
if (!config)
{
@@ -621,25 +597,26 @@ meta_monitor_manager_dummy_apply_monitors_config (MetaMonitorManager *manag
}
if (!meta_monitor_config_manager_assign (manager, config,
&crtc_infos, &output_infos,
&crtc_assignments,
&output_assignments,
error))
return FALSE;
if (method == META_MONITORS_CONFIG_METHOD_VERIFY)
{
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
g_ptr_array_free (crtc_assignments, TRUE);
g_ptr_array_free (output_assignments, TRUE);
return TRUE;
}
apply_crtc_assignments (manager,
(MetaCrtcInfo **) crtc_infos->pdata,
crtc_infos->len,
(MetaOutputInfo **) output_infos->pdata,
output_infos->len);
(MetaCrtcAssignment **) crtc_assignments->pdata,
crtc_assignments->len,
(MetaOutputAssignment **) output_assignments->pdata,
output_assignments->len);
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
g_ptr_array_free (crtc_assignments, TRUE);
g_ptr_array_free (output_assignments, TRUE);
update_screen_size (manager, config);
meta_monitor_manager_rebuild (manager, config);
@@ -666,7 +643,7 @@ meta_monitor_manager_dummy_calculate_monitor_mode_scale (MetaMonitorManager *man
MetaOutputDummy *output_dummy;
output = meta_monitor_get_main_output (monitor);
output_dummy = output->driver_private;
output_dummy = META_OUTPUT_DUMMY (output);
return output_dummy->scale;
}
@@ -813,3 +790,24 @@ meta_gpu_dummy_class_init (MetaGpuDummyClass *klass)
gpu_class->read_current = meta_gpu_dummy_read_current;
}
static void
meta_output_dummy_init (MetaOutputDummy *output_dummy)
{
output_dummy->scale = 1;
}
static void
meta_output_dummy_class_init (MetaOutputDummyClass *klass)
{
}
static void
meta_crtc_dummy_init (MetaCrtcDummy *crtc_dummy)
{
}
static void
meta_crtc_dummy_class_init (MetaCrtcDummyClass *klass)
{
}

View File

@@ -23,8 +23,20 @@
#ifndef META_MONITOR_MANAGER_DUMMY_H
#define META_MONITOR_MANAGER_DUMMY_H
#include "backends/meta-crtc.h"
#include "backends/meta-gpu.h"
#include "backends/meta-monitor-manager-private.h"
#include "backends/meta-output.h"
#define META_TYPE_OUTPUT_DUMMY (meta_output_dummy_get_type ())
G_DECLARE_FINAL_TYPE (MetaOutputDummy, meta_output_dummy,
META, OUTPUT_DUMMY,
MetaOutput)
#define META_TYPE_CRTC_DUMMY (meta_crtc_dummy_get_type ())
G_DECLARE_FINAL_TYPE (MetaCrtcDummy, meta_crtc_dummy,
META, CRTC_DUMMY,
MetaCrtc)
#define META_TYPE_MONITOR_MANAGER_DUMMY (meta_monitor_manager_dummy_get_type ())
G_DECLARE_FINAL_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy,

View File

@@ -63,12 +63,12 @@ typedef enum _MetaLogicalMonitorLayoutMode
} MetaLogicalMonitorLayoutMode;
/*
* MetaCrtcInfo:
* MetaCrtcAssignment:
*
* A representation of a CRTC configuration, generated by
* MetaMonitorConfigManager.
*/
struct _MetaCrtcInfo
struct _MetaCrtcAssignment
{
MetaCrtc *crtc;
MetaCrtcMode *mode;
@@ -78,12 +78,12 @@ struct _MetaCrtcInfo
};
/*
* MetaOutputInfo:
* MetaOutputAssignment:
*
* A representation of a connector configuration, generated by
* MetaMonitorConfigManager.
*/
struct _MetaOutputInfo
struct _MetaOutputAssignment
{
MetaOutput *output;
gboolean is_primary;
@@ -387,4 +387,22 @@ gboolean meta_monitor_has_aspect_as_size (MetaMonitor *monitor);
char * meta_monitor_manager_get_vendor_name (MetaMonitorManager *manager,
const char *vendor);
static inline MetaOutputAssignment *
meta_find_output_assignment (MetaOutputAssignment **outputs,
unsigned int n_outputs,
MetaOutput *output)
{
unsigned int i;
for (i = 0; i < n_outputs; i++)
{
MetaOutputAssignment *output_assignment = outputs[i];
if (output == output_assignment->output)
return output_assignment;
}
return NULL;
}
#endif /* META_MONITOR_MANAGER_PRIVATE_H */

View File

@@ -140,7 +140,10 @@ meta_monitor_manager_set_primary_logical_monitor (MetaMonitorManager *manager,
static gboolean
is_main_tiled_monitor_output (MetaOutput *output)
{
return output->tile_info.loc_h_tile == 0 && output->tile_info.loc_v_tile == 0;
const MetaOutputInfo *output_info = meta_output_get_info (output);
return (output_info->tile_info.loc_h_tile == 0 &&
output_info->tile_info.loc_v_tile == 0);
}
static MetaLogicalMonitor *
@@ -1014,15 +1017,16 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
{
MetaCrtc *crtc = l->data;
GVariantBuilder transforms;
MetaCrtcConfig *crtc_config;
const MetaCrtcConfig *crtc_config;
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
if (crtc->all_transforms & (1 << j))
g_variant_builder_add (&transforms, "u", j);
crtc_config = crtc->config;
{
if (meta_crtc_get_all_transforms (crtc) & (1 << j))
g_variant_builder_add (&transforms, "u", j);
}
crtc_config = meta_crtc_get_config (crtc);
if (crtc_config)
{
int current_mode_index;
@@ -1030,7 +1034,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
current_mode_index = g_list_index (combined_modes, crtc_config->mode);
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
i, /* ID */
(int64_t) crtc->crtc_id,
(int64_t) meta_crtc_get_id (crtc),
(int) roundf (crtc_config->layout.origin.x),
(int) roundf (crtc_config->layout.origin.y),
(int) roundf (crtc_config->layout.size.width),
@@ -1044,7 +1048,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
{
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
i, /* ID */
(int64_t) crtc->crtc_id,
(int64_t) meta_crtc_get_id (crtc),
0,
0,
0,
@@ -1059,15 +1063,23 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
for (l = combined_outputs, i = 0; l; l = l->next, i++)
{
MetaOutput *output = l->data;
const MetaOutputInfo *output_info = meta_output_get_info (output);
GVariantBuilder crtcs, modes, clones, properties;
GBytes *edid;
MetaCrtc *crtc;
int crtc_index;
int backlight;
int min_backlight_step;
gboolean is_primary;
gboolean is_presentation;
const char * connector_type_name;
gboolean is_underscanning;
gboolean supports_underscanning;
g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au"));
for (j = 0; j < output->n_possible_crtcs; j++)
for (j = 0; j < output_info->n_possible_crtcs; j++)
{
MetaCrtc *possible_crtc = output->possible_crtcs[j];
MetaCrtc *possible_crtc = output_info->possible_crtcs[j];
unsigned possible_crtc_index;
possible_crtc_index = g_list_index (combined_crtcs, possible_crtc);
@@ -1075,52 +1087,62 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
}
g_variant_builder_init (&modes, G_VARIANT_TYPE ("au"));
for (j = 0; j < output->n_modes; j++)
for (j = 0; j < output_info->n_modes; j++)
{
unsigned mode_index;
mode_index = g_list_index (combined_modes, output->modes[j]);
mode_index = g_list_index (combined_modes, output_info->modes[j]);
g_variant_builder_add (&modes, "u", mode_index);
}
g_variant_builder_init (&clones, G_VARIANT_TYPE ("au"));
for (j = 0; j < output->n_possible_clones; j++)
for (j = 0; j < output_info->n_possible_clones; j++)
{
unsigned int possible_clone_index;
possible_clone_index = g_list_index (combined_outputs,
output->possible_clones[j]);
output_info->possible_clones[j]);
g_variant_builder_add (&clones, "u", possible_clone_index);
}
backlight = meta_output_get_backlight (output);
min_backlight_step =
output_info->backlight_max - output_info->backlight_min
? 100 / (output_info->backlight_max - output_info->backlight_min)
: -1;
is_primary = meta_output_is_primary (output);
is_presentation = meta_output_is_presentation (output);
is_underscanning = meta_output_is_underscanning (output);
connector_type_name = get_connector_type_name (output_info->connector_type);
supports_underscanning = output_info->supports_underscanning;
g_variant_builder_init (&properties, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&properties, "{sv}", "vendor",
g_variant_new_string (output->vendor));
g_variant_new_string (output_info->vendor));
g_variant_builder_add (&properties, "{sv}", "product",
g_variant_new_string (output->product));
g_variant_new_string (output_info->product));
g_variant_builder_add (&properties, "{sv}", "serial",
g_variant_new_string (output->serial));
g_variant_new_string (output_info->serial));
g_variant_builder_add (&properties, "{sv}", "width-mm",
g_variant_new_int32 (output->width_mm));
g_variant_new_int32 (output_info->width_mm));
g_variant_builder_add (&properties, "{sv}", "height-mm",
g_variant_new_int32 (output->height_mm));
g_variant_new_int32 (output_info->height_mm));
g_variant_builder_add (&properties, "{sv}", "display-name",
g_variant_new_string (output->name));
g_variant_new_string (output_info->name));
g_variant_builder_add (&properties, "{sv}", "backlight",
g_variant_new_int32 (output->backlight));
g_variant_new_int32 (backlight));
g_variant_builder_add (&properties, "{sv}", "min-backlight-step",
g_variant_new_int32 ((output->backlight_max - output->backlight_min) ?
100 / (output->backlight_max - output->backlight_min) : -1));
g_variant_new_int32 (min_backlight_step));
g_variant_builder_add (&properties, "{sv}", "primary",
g_variant_new_boolean (output->is_primary));
g_variant_new_boolean (is_primary));
g_variant_builder_add (&properties, "{sv}", "presentation",
g_variant_new_boolean (output->is_presentation));
g_variant_new_boolean (is_presentation));
g_variant_builder_add (&properties, "{sv}", "connector-type",
g_variant_new_string (get_connector_type_name (output->connector_type)));
g_variant_new_string (connector_type_name));
g_variant_builder_add (&properties, "{sv}", "underscanning",
g_variant_new_boolean (output->is_underscanning));
g_variant_new_boolean (is_underscanning));
g_variant_builder_add (&properties, "{sv}", "supports-underscanning",
g_variant_new_boolean (output->supports_underscanning));
g_variant_new_boolean (supports_underscanning));
edid = manager_class->read_edid (manager, output);
if (edid)
@@ -1131,28 +1153,30 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_bytes_unref (edid);
}
if (output->tile_info.group_id)
if (output_info->tile_info.group_id)
{
g_variant_builder_add (&properties, "{sv}", "tile",
g_variant_new ("(uuuuuuuu)",
output->tile_info.group_id,
output->tile_info.flags,
output->tile_info.max_h_tiles,
output->tile_info.max_v_tiles,
output->tile_info.loc_h_tile,
output->tile_info.loc_v_tile,
output->tile_info.tile_w,
output->tile_info.tile_h));
GVariant *tile_variant;
tile_variant = g_variant_new ("(uuuuuuuu)",
output_info->tile_info.group_id,
output_info->tile_info.flags,
output_info->tile_info.max_h_tiles,
output_info->tile_info.max_v_tiles,
output_info->tile_info.loc_h_tile,
output_info->tile_info.loc_v_tile,
output_info->tile_info.tile_w,
output_info->tile_info.tile_h);
g_variant_builder_add (&properties, "{sv}", "tile", tile_variant);
}
crtc = meta_output_get_assigned_crtc (output);
crtc_index = crtc ? g_list_index (combined_crtcs, crtc) : -1;
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */
(gint64)output->winsys_id,
meta_output_get_id (output),
crtc_index,
&crtcs,
output->name,
meta_output_get_name (output),
&modes,
&clones,
&properties);
@@ -1161,14 +1185,16 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
for (l = combined_modes, i = 0; l; l = l->next, i++)
{
MetaCrtcMode *mode = l->data;
const MetaCrtcModeInfo *crtc_mode_info =
meta_crtc_mode_get_info (mode);;
g_variant_builder_add (&mode_builder, "(uxuudu)",
i, /* ID */
(gint64)mode->mode_id,
(guint32)mode->width,
(guint32)mode->height,
(double)mode->refresh_rate,
(guint32)mode->flags);
(int64_t) meta_crtc_mode_get_id (mode),
(uint32_t) crtc_mode_info->width,
(uint32_t) crtc_mode_info->height,
(double) crtc_mode_info->refresh_rate,
(uint32_t) crtc_mode_info->flags);
}
if (!meta_monitor_manager_get_max_screen_size (manager,
@@ -2103,6 +2129,8 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
{
GList *combined_outputs;
MetaOutput *output;
const MetaOutputInfo *output_info;
int new_backlight;
if (serial != manager->serial)
{
@@ -2133,8 +2161,10 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
return TRUE;
}
if (output->backlight == -1 ||
(output->backlight_min == 0 && output->backlight_max == 0))
output_info = meta_output_get_info (output);
if (meta_output_get_backlight (output) == -1 ||
(output_info->backlight_min == 0 &&
output_info->backlight_max == 0))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
@@ -2144,7 +2174,10 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
META_MONITOR_MANAGER_GET_CLASS (manager)->change_backlight (manager, output, value);
meta_dbus_display_config_complete_change_backlight (skeleton, invocation, output->backlight);
new_backlight = meta_output_get_backlight (output);
meta_dbus_display_config_complete_change_backlight (skeleton,
invocation,
new_backlight);
return TRUE;
}
@@ -2649,8 +2682,9 @@ rebuild_monitors (MetaMonitorManager *manager)
for (k = meta_gpu_get_outputs (gpu); k; k = k->next)
{
MetaOutput *output = k->data;
const MetaOutputInfo *output_info = meta_output_get_info (output);
if (output->tile_info.group_id)
if (output_info->tile_info.group_id)
{
if (is_main_tiled_monitor_output (output))
{
@@ -2882,8 +2916,8 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager,
}
void
meta_output_parse_edid (MetaOutput *output,
GBytes *edid)
meta_output_info_parse_edid (MetaOutputInfo *output_info,
GBytes *edid)
{
MonitorInfo *parsed_edid;
gsize len;
@@ -2895,43 +2929,44 @@ meta_output_parse_edid (MetaOutput *output,
if (parsed_edid)
{
output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
if (!g_utf8_validate (output->vendor, -1, NULL))
g_clear_pointer (&output->vendor, g_free);
output_info->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
if (!g_utf8_validate (output_info->vendor, -1, NULL))
g_clear_pointer (&output_info->vendor, g_free);
output->product = g_strndup (parsed_edid->dsc_product_name, 14);
if (!g_utf8_validate (output->product, -1, NULL) ||
output->product[0] == '\0')
output_info->product = g_strndup (parsed_edid->dsc_product_name, 14);
if (!g_utf8_validate (output_info->product, -1, NULL) ||
output_info->product[0] == '\0')
{
g_clear_pointer (&output->product, g_free);
output->product = g_strdup_printf ("0x%04x", (unsigned) parsed_edid->product_code);
g_clear_pointer (&output_info->product, g_free);
output_info->product = g_strdup_printf ("0x%04x", (unsigned) parsed_edid->product_code);
}
output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
if (!g_utf8_validate (output->serial, -1, NULL) ||
output->serial[0] == '\0')
output_info->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
if (!g_utf8_validate (output_info->serial, -1, NULL) ||
output_info->serial[0] == '\0')
{
g_clear_pointer (&output->serial, g_free);
output->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number);
g_clear_pointer (&output_info->serial, g_free);
output_info->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number);
}
g_free (parsed_edid);
}
out:
if (!output->vendor)
output->vendor = g_strdup ("unknown");
if (!output->product)
output->product = g_strdup ("unknown");
if (!output->serial)
output->serial = g_strdup ("unknown");
if (!output_info->vendor)
output_info->vendor = g_strdup ("unknown");
if (!output_info->product)
output_info->product = g_strdup ("unknown");
if (!output_info->serial)
output_info->serial = g_strdup ("unknown");
}
gboolean
meta_output_is_laptop (MetaOutput *output)
{
/* FIXME: extend with better heuristics */
switch (output->connector_type)
const MetaOutputInfo *output_info = meta_output_get_info (output);
switch (output_info->connector_type)
{
case META_CONNECTOR_TYPE_eDP:
case META_CONNECTOR_TYPE_LVDS:

View File

@@ -36,6 +36,7 @@ enum _MetaMonitorTransform
META_MONITOR_TRANSFORM_FLIPPED_270,
};
#define META_MONITOR_N_TRANSFORMS (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)
#define META_MONITOR_ALL_TRANSFORMS ((1 << META_MONITOR_N_TRANSFORMS) - 1)
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */

View File

@@ -168,19 +168,28 @@ meta_monitor_spec_free (MetaMonitorSpec *monitor_spec)
g_free (monitor_spec);
}
static const MetaOutputInfo *
meta_monitor_get_main_output_info (MetaMonitor *monitor)
{
MetaOutput *output = meta_monitor_get_main_output (monitor);
return meta_output_get_info (output);
}
static void
meta_monitor_generate_spec (MetaMonitor *monitor)
{
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
MetaOutput *output = meta_monitor_get_main_output (monitor);
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
MetaMonitorSpec *monitor_spec;
monitor_spec = g_new0 (MetaMonitorSpec, 1);
*monitor_spec = (MetaMonitorSpec) {
.connector = g_strdup (output->name),
.vendor = g_strdup (output->vendor),
.product = g_strdup (output->product),
.serial = g_strdup (output->serial),
.connector = g_strdup (output_info->name),
.vendor = g_strdup (output_info->vendor),
.product = g_strdup (output_info->product),
.serial = g_strdup (output_info->serial),
};
priv->spec = monitor_spec;
@@ -316,17 +325,16 @@ meta_monitor_is_primary (MetaMonitor *monitor)
output = meta_monitor_get_main_output (monitor);
return output->is_primary;
return meta_output_is_primary (output);
}
gboolean
meta_monitor_supports_underscanning (MetaMonitor *monitor)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
return output->supports_underscanning;
return output_info->supports_underscanning;
}
gboolean
@@ -336,17 +344,16 @@ meta_monitor_is_underscanning (MetaMonitor *monitor)
output = meta_monitor_get_main_output (monitor);
return output->is_underscanning;
return meta_output_is_underscanning (output);
}
gboolean
meta_monitor_is_laptop_panel (MetaMonitor *monitor)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
switch (output->connector_type)
switch (output_info->connector_type)
{
case META_CONNECTOR_TYPE_eDP:
case META_CONNECTOR_TYPE_LVDS:
@@ -392,65 +399,65 @@ meta_monitor_get_physical_dimensions (MetaMonitor *monitor,
int *width_mm,
int *height_mm)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
*width_mm = output->width_mm;
*height_mm = output->height_mm;
*width_mm = output_info->width_mm;
*height_mm = output_info->height_mm;
}
CoglSubpixelOrder
meta_monitor_get_subpixel_order (MetaMonitor *monitor)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
return output->subpixel_order;
return output_info->subpixel_order;
}
const char *
meta_monitor_get_connector (MetaMonitor *monitor)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
return output->name;
return output_info->name;
}
const char *
meta_monitor_get_vendor (MetaMonitor *monitor)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
return output->vendor;
return output_info->vendor;
}
const char *
meta_monitor_get_product (MetaMonitor *monitor)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
return output->product;
return output_info->product;
}
const char *
meta_monitor_get_serial (MetaMonitor *monitor)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
return output->serial;
return output_info->serial;
}
MetaConnectorType
meta_monitor_get_connector_type (MetaMonitor *monitor)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
return output->connector_type;
return output_info->connector_type;
}
MetaMonitorTransform
@@ -562,9 +569,12 @@ meta_monitor_create_spec (MetaMonitor *monitor,
int height,
MetaCrtcMode *crtc_mode)
{
MetaOutput *output = meta_monitor_get_main_output (monitor);
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
const MetaCrtcModeInfo *crtc_mode_info =
meta_crtc_mode_get_info (crtc_mode);
if (meta_monitor_transform_is_rotated (output->panel_orientation_transform))
if (meta_monitor_transform_is_rotated (output_info->panel_orientation_transform))
{
int temp = width;
width = height;
@@ -574,8 +584,8 @@ meta_monitor_create_spec (MetaMonitor *monitor,
return (MetaMonitorModeSpec) {
.width = width,
.height = height,
.refresh_rate = crtc_mode->refresh_rate,
.flags = crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
.refresh_rate = crtc_mode_info->refresh_rate,
.flags = crtc_mode_info->flags & HANDLED_CRTC_MODE_FLAGS
};
}
@@ -586,15 +596,21 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
MetaMonitorPrivate *monitor_priv =
meta_monitor_get_instance_private (monitor);
MetaOutput *output;
const MetaOutputInfo *output_info;
MetaCrtcMode *preferred_mode;
MetaCrtcModeFlag preferred_mode_flags;
unsigned int i;
output = meta_monitor_get_main_output (monitor);
preferred_mode_flags = output->preferred_mode->flags;
output_info = meta_output_get_info (output);
preferred_mode = output_info->preferred_mode;
preferred_mode_flags = meta_crtc_mode_get_info (preferred_mode)->flags;
for (i = 0; i < output->n_modes; i++)
for (i = 0; i < output_info->n_modes; i++)
{
MetaCrtcMode *crtc_mode = output->modes[i];
MetaCrtcMode *crtc_mode = output_info->modes[i];
const MetaCrtcModeInfo *crtc_mode_info =
meta_crtc_mode_get_info (crtc_mode);
MetaCrtc *crtc;
MetaMonitorMode *mode;
gboolean replace;
@@ -602,8 +618,8 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
mode = g_new0 (MetaMonitorMode, 1);
mode->monitor = monitor;
mode->spec = meta_monitor_create_spec (monitor,
crtc_mode->width,
crtc_mode->height,
crtc_mode_info->width,
crtc_mode_info->height,
crtc_mode);
mode->id = generate_mode_id (&mode->spec);
mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1);
@@ -619,21 +635,27 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
* otherwise take the first one in the list. This guarantees that the
* preferred mode is always added.
*/
replace = crtc_mode->flags == preferred_mode_flags;
replace = crtc_mode_info->flags == preferred_mode_flags;
if (!meta_monitor_add_mode (monitor, mode, replace))
{
g_assert (crtc_mode != output->preferred_mode);
g_assert (crtc_mode != output_info->preferred_mode);
meta_monitor_mode_free (mode);
continue;
}
if (crtc_mode == output->preferred_mode)
if (crtc_mode == output_info->preferred_mode)
monitor_priv->preferred_mode = mode;
crtc = meta_output_get_assigned_crtc (output);
if (crtc && crtc->config && crtc_mode == crtc->config->mode)
monitor_priv->current_mode = mode;
if (crtc)
{
const MetaCrtcConfig *crtc_config;
crtc_config = meta_crtc_get_config (crtc);
if (crtc_config && crtc_mode == crtc_config->mode)
monitor_priv->current_mode = mode;
}
}
}
@@ -653,7 +675,7 @@ meta_monitor_normal_new (MetaGpu *gpu,
monitor_priv->gpu = gpu;
monitor_priv->outputs = g_list_append (NULL, g_object_ref (output));
monitor_priv->winsys_id = output->winsys_id;
monitor_priv->winsys_id = meta_output_get_id (output);
meta_monitor_generate_spec (monitor);
meta_monitor_normal_generate_modes (monitor_normal);
@@ -679,11 +701,11 @@ meta_monitor_normal_derive_layout (MetaMonitor *monitor,
{
MetaOutput *output;
MetaCrtc *crtc;
MetaCrtcConfig *crtc_config;
const MetaCrtcConfig *crtc_config;
output = meta_monitor_get_main_output (monitor);
crtc = meta_output_get_assigned_crtc (output);
crtc_config = crtc->config;
crtc_config = meta_crtc_get_config (crtc);
g_return_if_fail (crtc_config);
@@ -697,14 +719,17 @@ meta_monitor_normal_get_suggested_position (MetaMonitor *monitor,
int *x,
int *y)
{
MetaOutput *output;
const MetaOutputInfo *output_info =
meta_monitor_get_main_output_info (monitor);
output = meta_monitor_get_main_output (monitor);
if (output->suggested_x < 0 && output->suggested_y < 0)
if (!output_info->hotplug_mode_update)
return FALSE;
*x = output->suggested_x;
*y = output->suggested_y;
if (output_info->suggested_x < 0 && output_info->suggested_y < 0)
return FALSE;
*x = output_info->suggested_x;
*y = output_info->suggested_y;
return TRUE;
}
@@ -765,12 +790,15 @@ add_tiled_monitor_outputs (MetaGpu *gpu,
for (l = outputs; l; l = l->next)
{
MetaOutput *output = l->data;
const MetaOutputInfo *output_info = meta_output_get_info (output);
const MetaOutputInfo *origin_output_info;
if (output->tile_info.group_id != monitor_tiled->tile_group_id)
if (output_info->tile_info.group_id != monitor_tiled->tile_group_id)
continue;
g_warn_if_fail (output->subpixel_order ==
monitor_tiled->origin_output->subpixel_order);
origin_output_info = meta_output_get_info (monitor_tiled->origin_output);
g_warn_if_fail (output_info->subpixel_order ==
origin_output_info->subpixel_order);
monitor_priv->outputs = g_list_append (monitor_priv->outputs,
g_object_ref (output));
@@ -786,51 +814,68 @@ calculate_tile_coordinate (MetaMonitor *monitor,
{
MetaMonitorPrivate *monitor_priv =
meta_monitor_get_instance_private (monitor);
const MetaOutputInfo *output_info = meta_output_get_info (output);
GList *l;
int x = 0;
int y = 0;
for (l = monitor_priv->outputs; l; l = l->next)
{
MetaOutput *other_output = l->data;
const MetaOutputInfo *other_output_info = meta_output_get_info (l->data);
switch (crtc_transform)
{
case META_MONITOR_TRANSFORM_NORMAL:
case META_MONITOR_TRANSFORM_FLIPPED:
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile)
x += other_output->tile_info.tile_w;
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile)
y += other_output->tile_info.tile_h;
if ((other_output_info->tile_info.loc_v_tile ==
output_info->tile_info.loc_v_tile) &&
(other_output_info->tile_info.loc_h_tile <
output_info->tile_info.loc_h_tile))
x += other_output_info->tile_info.tile_w;
if ((other_output_info->tile_info.loc_h_tile ==
output_info->tile_info.loc_h_tile) &&
(other_output_info->tile_info.loc_v_tile <
output_info->tile_info.loc_v_tile))
y += other_output_info->tile_info.tile_h;
break;
case META_MONITOR_TRANSFORM_180:
case META_MONITOR_TRANSFORM_FLIPPED_180:
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile)
x += other_output->tile_info.tile_w;
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile)
y += other_output->tile_info.tile_h;
if ((other_output_info->tile_info.loc_v_tile ==
output_info->tile_info.loc_v_tile) &&
(other_output_info->tile_info.loc_h_tile >
output_info->tile_info.loc_h_tile))
x += other_output_info->tile_info.tile_w;
if ((other_output_info->tile_info.loc_h_tile ==
output_info->tile_info.loc_h_tile) &&
(other_output_info->tile_info.loc_v_tile >
output_info->tile_info.loc_v_tile))
y += other_output_info->tile_info.tile_h;
break;
case META_MONITOR_TRANSFORM_270:
case META_MONITOR_TRANSFORM_FLIPPED_270:
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile)
y += other_output->tile_info.tile_w;
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile)
x += other_output->tile_info.tile_h;
if ((other_output_info->tile_info.loc_v_tile ==
output_info->tile_info.loc_v_tile) &&
(other_output_info->tile_info.loc_h_tile >
output_info->tile_info.loc_h_tile))
y += other_output_info->tile_info.tile_w;
if ((other_output_info->tile_info.loc_h_tile ==
output_info->tile_info.loc_h_tile) &&
(other_output_info->tile_info.loc_v_tile >
output_info->tile_info.loc_v_tile))
x += other_output_info->tile_info.tile_h;
break;
case META_MONITOR_TRANSFORM_90:
case META_MONITOR_TRANSFORM_FLIPPED_90:
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile)
y += other_output->tile_info.tile_w;
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile)
x += other_output->tile_info.tile_h;
if ((other_output_info->tile_info.loc_v_tile ==
output_info->tile_info.loc_v_tile) &&
(other_output_info->tile_info.loc_h_tile <
output_info->tile_info.loc_h_tile))
y += other_output_info->tile_info.tile_w;
if ((other_output_info->tile_info.loc_h_tile ==
output_info->tile_info.loc_h_tile) &&
(other_output_info->tile_info.loc_v_tile <
output_info->tile_info.loc_v_tile))
x += other_output_info->tile_info.tile_h;
break;
}
}
@@ -854,13 +899,13 @@ meta_monitor_tiled_calculate_tiled_size (MetaMonitor *monitor,
height = 0;
for (l = monitor_priv->outputs; l; l = l->next)
{
MetaOutput *output = l->data;
const MetaOutputInfo *output_info = meta_output_get_info (l->data);
if (output->tile_info.loc_v_tile == 0)
width += output->tile_info.tile_w;
if (output_info->tile_info.loc_v_tile == 0)
width += output_info->tile_info.tile_w;
if (output->tile_info.loc_h_tile == 0)
height += output->tile_info.tile_h;
if (output_info->tile_info.loc_h_tile == 0)
height += output_info->tile_info.tile_h;
}
*out_width = width;
@@ -880,11 +925,14 @@ is_monitor_mode_assigned (MetaMonitor *monitor,
MetaOutput *output = l->data;
MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i];
MetaCrtc *crtc;
const MetaCrtcConfig *crtc_config;
crtc = meta_output_get_assigned_crtc (output);
crtc_config = crtc ? meta_crtc_get_config (crtc) : NULL;
if (monitor_crtc_mode->crtc_mode &&
(!crtc || !crtc->config ||
crtc->config->mode != monitor_crtc_mode->crtc_mode))
(!crtc || !crtc_config ||
crtc_config->mode != monitor_crtc_mode->crtc_mode))
return FALSE;
else if (!monitor_crtc_mode->crtc_mode && crtc)
return FALSE;
@@ -897,32 +945,41 @@ static gboolean
is_crtc_mode_tiled (MetaOutput *output,
MetaCrtcMode *crtc_mode)
{
return (crtc_mode->width == (int) output->tile_info.tile_w &&
crtc_mode->height == (int) output->tile_info.tile_h);
const MetaOutputInfo *output_info = meta_output_get_info (output);
const MetaCrtcModeInfo *crtc_mode_info = meta_crtc_mode_get_info (crtc_mode);
return (crtc_mode_info->width == (int) output_info->tile_info.tile_w &&
crtc_mode_info->height == (int) output_info->tile_info.tile_h);
}
static MetaCrtcMode *
find_tiled_crtc_mode (MetaOutput *output,
MetaCrtcMode *reference_crtc_mode)
{
const MetaOutputInfo *output_info = meta_output_get_info (output);
const MetaCrtcModeInfo *reference_crtc_mode_info =
meta_crtc_mode_get_info (reference_crtc_mode);
MetaCrtcMode *crtc_mode;
unsigned int i;
crtc_mode = output->preferred_mode;
crtc_mode = output_info->preferred_mode;
if (is_crtc_mode_tiled (output, crtc_mode))
return crtc_mode;
for (i = 0; i < output->n_modes; i++)
for (i = 0; i < output_info->n_modes; i++)
{
crtc_mode = output->modes[i];
const MetaCrtcModeInfo *crtc_mode_info;
crtc_mode = output_info->modes[i];
crtc_mode_info = meta_crtc_mode_get_info (crtc_mode);
if (!is_crtc_mode_tiled (output, crtc_mode))
continue;
if (crtc_mode->refresh_rate != reference_crtc_mode->refresh_rate)
if (crtc_mode_info->refresh_rate != reference_crtc_mode_info->refresh_rate)
continue;
if (crtc_mode->flags != reference_crtc_mode->flags)
if (crtc_mode_info->flags != reference_crtc_mode_info->flags)
continue;
return crtc_mode;
@@ -958,12 +1015,13 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
{
MetaOutput *output = l->data;
const MetaOutputInfo *output_info = meta_output_get_info (output);
MetaCrtcMode *tiled_crtc_mode;
tiled_crtc_mode = find_tiled_crtc_mode (output, reference_crtc_mode);
if (!tiled_crtc_mode)
{
g_warning ("No tiled mode found on %s", output->name);
g_warning ("No tiled mode found on %s", meta_output_get_name (output));
meta_monitor_mode_free ((MetaMonitorMode *) mode);
return NULL;
}
@@ -973,7 +1031,8 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
.crtc_mode = tiled_crtc_mode
};
is_preferred = is_preferred && tiled_crtc_mode == output->preferred_mode;
is_preferred = (is_preferred &&
tiled_crtc_mode == output_info->preferred_mode);
}
*out_is_preferred = is_preferred;
@@ -988,16 +1047,18 @@ generate_tiled_monitor_modes (MetaMonitorTiled *monitor_tiled)
MetaMonitorPrivate *monitor_priv =
meta_monitor_get_instance_private (monitor);
MetaOutput *main_output;
const MetaOutputInfo *main_output_info;
GList *tiled_modes = NULL;
unsigned int i;
MetaMonitorMode *best_mode = NULL;
GList *l;
main_output = meta_monitor_get_main_output (META_MONITOR (monitor_tiled));
main_output_info = meta_output_get_info (main_output);
for (i = 0; i < main_output->n_modes; i++)
for (i = 0; i < main_output_info->n_modes; i++)
{
MetaCrtcMode *reference_crtc_mode = main_output->modes[i];
MetaCrtcMode *reference_crtc_mode = main_output_info->modes[i];
MetaMonitorMode *mode;
gboolean is_preferred;
@@ -1051,6 +1112,7 @@ create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
MetaMonitorPrivate *monitor_priv =
meta_monitor_get_instance_private (monitor);
MetaMonitorModeTiled *mode;
const MetaCrtcModeInfo *crtc_mode_info;
GList *l;
int i;
@@ -1060,9 +1122,11 @@ create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
mode = g_new0 (MetaMonitorModeTiled, 1);
mode->is_tiled = FALSE;
mode->parent.monitor = monitor;
crtc_mode_info = meta_crtc_mode_get_info (crtc_mode);
mode->parent.spec = meta_monitor_create_spec (monitor,
crtc_mode->width,
crtc_mode->height,
crtc_mode_info->width,
crtc_mode_info->height,
crtc_mode);
mode->parent.id = generate_mode_id (&mode->parent.spec);
mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
@@ -1094,13 +1158,14 @@ create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
static int
count_untiled_crtc_modes (MetaOutput *output)
{
const MetaOutputInfo *output_info = meta_output_get_info (output);
int count;
unsigned int i;
count = 0;
for (i = 0; i < output->n_modes; i++)
for (i = 0; i < output_info->n_modes; i++)
{
MetaCrtcMode *crtc_mode = output->modes[i];
MetaCrtcMode *crtc_mode = output_info->modes[i];
if (!is_crtc_mode_tiled (output, crtc_mode))
count++;
@@ -1149,13 +1214,15 @@ generate_untiled_monitor_modes (MetaMonitorTiled *monitor_tiled)
MetaMonitorPrivate *monitor_priv =
meta_monitor_get_instance_private (monitor);
MetaOutput *main_output;
const MetaOutputInfo *main_output_info;
unsigned int i;
main_output = meta_monitor_get_main_output (monitor);
main_output_info = meta_output_get_info (main_output);
for (i = 0; i < main_output->n_modes; i++)
for (i = 0; i < main_output_info->n_modes; i++)
{
MetaCrtcMode *crtc_mode = main_output->modes[i];
MetaCrtcMode *crtc_mode = main_output_info->modes[i];
MetaMonitorMode *mode;
mode = create_untiled_monitor_mode (monitor_tiled,
@@ -1177,7 +1244,7 @@ generate_untiled_monitor_modes (MetaMonitorTiled *monitor_tiled)
}
if (!monitor_priv->preferred_mode &&
crtc_mode == main_output->preferred_mode)
crtc_mode == main_output_info->preferred_mode)
monitor_priv->preferred_mode = mode;
}
}
@@ -1281,6 +1348,7 @@ meta_monitor_tiled_new (MetaGpu *gpu,
MetaMonitorManager *monitor_manager,
MetaOutput *output)
{
const MetaOutputInfo *output_info = meta_output_get_info (output);
MetaMonitorTiled *monitor_tiled;
MetaMonitor *monitor;
MetaMonitorPrivate *monitor_priv;
@@ -1291,8 +1359,8 @@ meta_monitor_tiled_new (MetaGpu *gpu,
monitor_priv->gpu = gpu;
monitor_tiled->tile_group_id = output->tile_info.group_id;
monitor_priv->winsys_id = output->winsys_id;
monitor_tiled->tile_group_id = output_info->tile_info.group_id;
monitor_priv->winsys_id = meta_output_get_id (output);
monitor_tiled->origin_output = output;
add_tiled_monitor_outputs (gpu, monitor_tiled);
@@ -1338,14 +1406,14 @@ meta_monitor_tiled_derive_layout (MetaMonitor *monitor,
{
MetaOutput *output = l->data;
MetaCrtc *crtc;
MetaCrtcConfig *crtc_config;
graphene_rect_t *crtc_layout;
const MetaCrtcConfig *crtc_config;
const graphene_rect_t *crtc_layout;
crtc = meta_output_get_assigned_crtc (output);
if (!crtc)
continue;
crtc_config = crtc->config;
crtc_config = meta_crtc_get_config (crtc);
g_return_if_fail (crtc_config);
crtc_layout = &crtc_config->layout;
@@ -1512,7 +1580,8 @@ is_current_mode_known (MetaMonitor *monitor)
output = meta_monitor_get_main_output (monitor);
crtc = meta_output_get_assigned_crtc (output);
return meta_monitor_is_active (monitor) == (crtc && crtc->config);
return (meta_monitor_is_active (monitor) ==
(crtc && meta_crtc_get_config (crtc)));
}
void

View File

@@ -21,35 +21,180 @@
#include "backends/meta-output.h"
enum
{
PROP_0,
PROP_ID,
PROP_GPU,
PROP_INFO,
N_PROPS
};
static GParamSpec *obj_props[N_PROPS];
typedef struct _MetaOutputPrivate
{
uint64_t id;
MetaGpu *gpu;
MetaOutputInfo *info;
/* The CRTC driving this output, NULL if the output is not enabled */
MetaCrtc *crtc;
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
int backlight;
} MetaOutputPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaOutput, meta_output, G_TYPE_OBJECT)
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaOutput, meta_output, G_TYPE_OBJECT)
G_DEFINE_BOXED_TYPE (MetaOutputInfo, meta_output_info,
meta_output_info_ref,
meta_output_info_unref)
MetaOutputInfo *
meta_output_info_new (void)
{
MetaOutputInfo *output_info;
output_info = g_new0 (MetaOutputInfo, 1);
g_ref_count_init (&output_info->ref_count);
return output_info;
}
MetaOutputInfo *
meta_output_info_ref (MetaOutputInfo *output_info)
{
g_ref_count_inc (&output_info->ref_count);
return output_info;
}
void
meta_output_info_unref (MetaOutputInfo *output_info)
{
if (g_ref_count_dec (&output_info->ref_count))
{
g_free (output_info->name);
g_free (output_info->vendor);
g_free (output_info->product);
g_free (output_info->serial);
g_free (output_info->modes);
g_free (output_info->possible_crtcs);
g_free (output_info->possible_clones);
g_free (output_info);
}
}
uint64_t
meta_output_get_id (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return priv->id;
}
MetaGpu *
meta_output_get_gpu (MetaOutput *output)
{
return output->gpu;
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return priv->gpu;
}
const char *
meta_output_get_name (MetaOutput *output)
{
return output->name;
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return priv->info->name;
}
gboolean
meta_output_is_primary (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return priv->is_primary;
}
gboolean
meta_output_is_presentation (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return priv->is_presentation;
}
gboolean
meta_output_is_underscanning (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return priv->is_underscanning;
}
void
meta_output_assign_crtc (MetaOutput *output,
MetaCrtc *crtc)
meta_output_set_backlight (MetaOutput *output,
int backlight)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
priv->backlight = backlight;
}
int
meta_output_get_backlight (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return priv->backlight;
}
void
meta_output_add_possible_clone (MetaOutput *output,
MetaOutput *possible_clone)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
MetaOutputInfo *output_info = priv->info;
output_info->n_possible_clones++;
output_info->possible_clones = g_renew (MetaOutput *,
output_info->possible_clones,
output_info->n_possible_clones);
output_info->possible_clones[output_info->n_possible_clones - 1] =
possible_clone;
}
const MetaOutputInfo *
meta_output_get_info (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return priv->info;
}
void
meta_output_assign_crtc (MetaOutput *output,
MetaCrtc *crtc,
const MetaOutputAssignment *output_assignment)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
g_assert (crtc);
g_set_object (&priv->crtc, crtc);
priv->is_primary = output_assignment->is_primary;
priv->is_presentation = output_assignment->is_presentation;
priv->is_underscanning = output_assignment->is_underscanning;
}
void
@@ -58,6 +203,9 @@ meta_output_unassign_crtc (MetaOutput *output)
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
g_clear_object (&priv->crtc);
priv->is_primary = FALSE;
priv->is_presentation = FALSE;
}
MetaCrtc *
@@ -72,9 +220,10 @@ MetaMonitorTransform
meta_output_logical_to_crtc_transform (MetaOutput *output,
MetaMonitorTransform transform)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
MetaMonitorTransform panel_orientation_transform;
panel_orientation_transform = output->panel_orientation_transform;
panel_orientation_transform = priv->info->panel_orientation_transform;
return meta_monitor_transform_transform (transform,
panel_orientation_transform);
}
@@ -83,14 +232,65 @@ MetaMonitorTransform
meta_output_crtc_to_logical_transform (MetaOutput *output,
MetaMonitorTransform transform)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
MetaMonitorTransform inverted_panel_orientation_transform;
inverted_panel_orientation_transform =
meta_monitor_transform_invert (output->panel_orientation_transform);
meta_monitor_transform_invert (priv->info->panel_orientation_transform);
return meta_monitor_transform_transform (transform,
inverted_panel_orientation_transform);
}
static void
meta_output_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaOutput *output = META_OUTPUT (object);
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
switch (prop_id)
{
case PROP_ID:
priv->id = g_value_get_uint64 (value);
break;
case PROP_GPU:
priv->gpu = g_value_get_object (value);
break;
case PROP_INFO:
priv->info = meta_output_info_ref (g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_output_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaOutput *output = META_OUTPUT (object);
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
switch (prop_id)
{
case PROP_ID:
g_value_set_uint64 (value, priv->id);
break;
case PROP_GPU:
g_value_set_object (value, priv->gpu);
break;
case PROP_INFO:
g_value_set_boxed (value, priv->info);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_output_dispose (GObject *object)
{
@@ -106,17 +306,9 @@ static void
meta_output_finalize (GObject *object)
{
MetaOutput *output = META_OUTPUT (object);
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
g_free (output->name);
g_free (output->vendor);
g_free (output->product);
g_free (output->serial);
g_free (output->modes);
g_free (output->possible_crtcs);
g_free (output->possible_clones);
if (output->driver_notify)
output->driver_notify (output);
g_clear_pointer (&priv->info, meta_output_info_unref);
G_OBJECT_CLASS (meta_output_parent_class)->finalize (object);
}
@@ -124,6 +316,9 @@ meta_output_finalize (GObject *object)
static void
meta_output_init (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
priv->backlight = -1;
}
static void
@@ -131,6 +326,34 @@ meta_output_class_init (MetaOutputClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = meta_output_set_property;
object_class->get_property = meta_output_get_property;
object_class->dispose = meta_output_dispose;
object_class->finalize = meta_output_finalize;
obj_props[PROP_ID] =
g_param_spec_uint64 ("id",
"id",
"CRTC id",
0, UINT64_MAX, 0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_GPU] =
g_param_spec_object ("gpu",
"gpu",
"MetaGpu",
META_TYPE_GPU,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_INFO] =
g_param_spec_boxed ("info",
"info",
"MetaOutputInfo",
META_TYPE_OUTPUT_INFO,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, obj_props);
}

View File

@@ -60,14 +60,10 @@ typedef enum
META_CONNECTOR_TYPE_DSI = 16,
} MetaConnectorType;
struct _MetaOutput
typedef struct _MetaOutputInfo
{
GObject parent;
grefcount ref_count;
MetaGpu *gpu;
/* The low-level ID of this output, used to apply back configuration */
uint64_t winsys_id;
char *name;
char *vendor;
char *product;
@@ -89,35 +85,52 @@ struct _MetaOutput
MetaOutput **possible_clones;
unsigned int n_possible_clones;
int backlight;
int backlight_min;
int backlight_max;
/* Used when changing configuration */
gboolean is_dirty;
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
gboolean supports_underscanning;
gpointer driver_private;
GDestroyNotify driver_notify;
/*
* Get a new preferred mode on hotplug events, to handle dynamic guest
* resizing.
*/
gboolean hotplug_mode_update;
gint suggested_x;
gint suggested_y;
int suggested_x;
int suggested_y;
MetaTileInfo tile_info;
};
} MetaOutputInfo;
#define META_TYPE_OUTPUT_INFO (meta_output_info_get_type ())
META_EXPORT_TEST
GType meta_output_info_get_type (void);
META_EXPORT_TEST
MetaOutputInfo * meta_output_info_new (void);
META_EXPORT_TEST
MetaOutputInfo * meta_output_info_ref (MetaOutputInfo *output_info);
META_EXPORT_TEST
void meta_output_info_unref (MetaOutputInfo *output_info);
META_EXPORT_TEST
void meta_output_info_parse_edid (MetaOutputInfo *output_info,
GBytes *edid);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaOutputInfo, meta_output_info_unref)
#define META_TYPE_OUTPUT (meta_output_get_type ())
META_EXPORT_TEST G_DECLARE_FINAL_TYPE (MetaOutput, meta_output, META, OUTPUT, GObject)
META_EXPORT_TEST
G_DECLARE_DERIVABLE_TYPE (MetaOutput, meta_output, META, OUTPUT, GObject)
struct _MetaOutputClass
{
GObjectClass parent_class;
};
META_EXPORT_TEST
uint64_t meta_output_get_id (MetaOutput *output);
META_EXPORT_TEST
MetaGpu * meta_output_get_gpu (MetaOutput *output);
@@ -125,8 +138,28 @@ MetaGpu * meta_output_get_gpu (MetaOutput *output);
const char * meta_output_get_name (MetaOutput *output);
META_EXPORT_TEST
void meta_output_assign_crtc (MetaOutput *output,
MetaCrtc *crtc);
gboolean meta_output_is_primary (MetaOutput *output);
META_EXPORT_TEST
gboolean meta_output_is_presentation (MetaOutput *output);
META_EXPORT_TEST
gboolean meta_output_is_underscanning (MetaOutput *output);
void meta_output_set_backlight (MetaOutput *output,
int backlight);
int meta_output_get_backlight (MetaOutput *output);
void meta_output_add_possible_clone (MetaOutput *output,
MetaOutput *possible_clone);
const MetaOutputInfo * meta_output_get_info (MetaOutput *output);
META_EXPORT_TEST
void meta_output_assign_crtc (MetaOutput *output,
MetaCrtc *crtc,
const MetaOutputAssignment *output_assignment);
META_EXPORT_TEST
void meta_output_unassign_crtc (MetaOutput *output);

View File

@@ -194,23 +194,8 @@ meta_renderer_is_hardware_accelerated (MetaRenderer *renderer)
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
CoglGpuInfo *info = &cogl_context->gpu;
switch (info->architecture)
{
case COGL_GPU_INFO_ARCHITECTURE_UNKNOWN:
case COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE:
case COGL_GPU_INFO_ARCHITECTURE_SGX:
case COGL_GPU_INFO_ARCHITECTURE_MALI:
return TRUE;
case COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE:
case COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE:
case COGL_GPU_INFO_ARCHITECTURE_SWRAST:
return FALSE;
}
g_assert_not_reached ();
return FALSE;
return cogl_context_is_hardware_accelerated (cogl_context);
}
static void

View File

@@ -42,6 +42,7 @@
#include "backends/meta-cursor-tracker-private.h"
#include "backends/meta-idle-monitor-private.h"
#include "backends/meta-keymap-utils.h"
#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor-manager-private.h"
#include "backends/meta-pointer-constraint.h"
@@ -340,7 +341,7 @@ meta_backend_native_create_clutter_backend (MetaBackend *backend)
static void
meta_backend_native_post_init (MetaBackend *backend)
{
ClutterBackend *clutter_backend = clutter_get_default_backend ();
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
MetaSettings *settings = meta_backend_get_settings (backend);
@@ -425,6 +426,7 @@ meta_backend_native_set_keymap (MetaBackend *backend,
const char *variants,
const char *options)
{
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
struct xkb_rule_names names;
struct xkb_keymap *keymap;
struct xkb_context *context;
@@ -436,11 +438,11 @@ meta_backend_native_set_keymap (MetaBackend *backend,
names.variant = variants;
names.options = options;
context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
context = meta_create_xkb_context ();
keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_context_unref (context);
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
seat = clutter_backend_get_default_seat (clutter_backend);
meta_seat_native_set_keyboard_map (META_SEAT_NATIVE (seat), keymap);
meta_backend_notify_keymap_changed (backend);
@@ -451,18 +453,20 @@ meta_backend_native_set_keymap (MetaBackend *backend,
static struct xkb_keymap *
meta_backend_native_get_keymap (MetaBackend *backend)
{
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
ClutterSeat *seat;
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
seat = clutter_backend_get_default_seat (clutter_backend);
return meta_seat_native_get_keyboard_map (META_SEAT_NATIVE (seat));
}
static xkb_layout_index_t
meta_backend_native_get_keymap_layout_group (MetaBackend *backend)
{
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
ClutterSeat *seat;
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
seat = clutter_backend_get_default_seat (clutter_backend);
return meta_seat_native_get_keyboard_layout_index (META_SEAT_NATIVE (seat));
}
@@ -470,6 +474,7 @@ static void
meta_backend_native_lock_layout_group (MetaBackend *backend,
guint idx)
{
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
xkb_layout_index_t old_idx;
ClutterSeat *seat;
@@ -477,7 +482,7 @@ meta_backend_native_lock_layout_group (MetaBackend *backend,
if (old_idx == idx)
return;
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
seat = clutter_backend_get_default_seat (clutter_backend);
meta_seat_native_set_keyboard_layout_index (META_SEAT_NATIVE (seat), idx);
meta_backend_notify_keymap_layout_group_changed (backend, idx);
}
@@ -486,9 +491,10 @@ static void
meta_backend_native_set_numlock (MetaBackend *backend,
gboolean numlock_state)
{
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
ClutterSeat *seat;
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
seat = clutter_backend_get_default_seat (clutter_backend);
meta_seat_native_set_keyboard_numlock (META_SEAT_NATIVE (seat),
numlock_state);
}
@@ -780,7 +786,7 @@ meta_backend_native_pause (MetaBackendNative *native)
meta_backend_get_monitor_manager (backend);
MetaMonitorManagerKms *monitor_manager_kms =
META_MONITOR_MANAGER_KMS (monitor_manager);
ClutterBackend *clutter_backend = clutter_get_default_backend ();
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
MetaSeatNative *seat =
META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
@@ -805,7 +811,7 @@ void meta_backend_native_resume (MetaBackendNative *native)
META_MONITOR_MANAGER_KMS (monitor_manager);
MetaInputSettings *input_settings;
MetaIdleMonitor *idle_monitor;
ClutterBackend *clutter_backend = clutter_get_default_backend ();
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
MetaSeatNative *seat =
META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));

View File

@@ -26,6 +26,7 @@
#include "backends/meta-backend-private.h"
#include "backends/meta-logical-monitor.h"
#include "backends/native/meta-crtc-mode-kms.h"
#include "backends/native/meta-gpu-kms.h"
#include "backends/native/meta-output-kms.h"
#include "backends/native/meta-kms-device.h"
@@ -34,21 +35,38 @@
#define ALL_TRANSFORMS_MASK ((1 << META_MONITOR_N_TRANSFORMS) - 1)
typedef struct _MetaCrtcKms
struct _MetaCrtcKms
{
MetaCrtc parent;
MetaKmsCrtc *kms_crtc;
MetaKmsPlane *primary_plane;
} MetaCrtcKms;
gpointer cursor_renderer_private;
};
static GQuark kms_crtc_crtc_kms_quark;
G_DEFINE_TYPE (MetaCrtcKms, meta_crtc_kms, META_TYPE_CRTC)
gpointer
meta_crtc_kms_get_cursor_renderer_private (MetaCrtcKms *crtc_kms)
{
return crtc_kms->cursor_renderer_private;
}
void
meta_crtc_kms_set_cursor_renderer_private (MetaCrtcKms *crtc_kms,
gpointer cursor_renderer_private)
{
crtc_kms->cursor_renderer_private = cursor_renderer_private;
}
gboolean
meta_crtc_kms_is_transform_handled (MetaCrtc *crtc,
meta_crtc_kms_is_transform_handled (MetaCrtcKms *crtc_kms,
MetaMonitorTransform transform)
{
MetaCrtcKms *crtc_kms = crtc->driver_private;
if (!crtc_kms->primary_plane)
return FALSE;
@@ -57,16 +75,19 @@ meta_crtc_kms_is_transform_handled (MetaCrtc *crtc,
}
void
meta_crtc_kms_apply_transform (MetaCrtc *crtc,
meta_crtc_kms_apply_transform (MetaCrtcKms *crtc_kms,
MetaKmsPlaneAssignment *kms_plane_assignment)
{
MetaCrtcKms *crtc_kms = crtc->driver_private;
MetaCrtc *crtc = META_CRTC (crtc_kms);
const MetaCrtcConfig *crtc_config;
MetaMonitorTransform hw_transform;
hw_transform = crtc->config->transform;
if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform))
crtc_config = meta_crtc_get_config (crtc);
hw_transform = crtc_config->transform;
if (!meta_crtc_kms_is_transform_handled (crtc_kms, hw_transform))
hw_transform = META_MONITOR_TRANSFORM_NORMAL;
if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform))
if (!meta_crtc_kms_is_transform_handled (crtc_kms, hw_transform))
return;
meta_kms_plane_update_set_rotation (crtc_kms->primary_plane,
@@ -75,11 +96,13 @@ meta_crtc_kms_apply_transform (MetaCrtc *crtc,
}
void
meta_crtc_kms_assign_primary_plane (MetaCrtc *crtc,
meta_crtc_kms_assign_primary_plane (MetaCrtcKms *crtc_kms,
uint32_t fb_id,
MetaKmsUpdate *kms_update)
{
MetaCrtcConfig *crtc_config;
MetaCrtc *crtc = META_CRTC (crtc_kms);
const MetaCrtcConfig *crtc_config;
const MetaCrtcModeInfo *crtc_mode_info;
MetaFixed16Rectangle src_rect;
MetaFixed16Rectangle dst_rect;
MetaKmsAssignPlaneFlag flags;
@@ -88,25 +111,25 @@ meta_crtc_kms_assign_primary_plane (MetaCrtc *crtc,
MetaKmsPlane *primary_kms_plane;
MetaKmsPlaneAssignment *plane_assignment;
crtc_config = crtc->config;
crtc_config = meta_crtc_get_config (crtc);
crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode);
src_rect = (MetaFixed16Rectangle) {
.x = meta_fixed_16_from_int (0),
.y = meta_fixed_16_from_int (0),
.width = meta_fixed_16_from_int (crtc_config->mode->width),
.height = meta_fixed_16_from_int (crtc_config->mode->height),
.width = meta_fixed_16_from_int (crtc_mode_info->width),
.height = meta_fixed_16_from_int (crtc_mode_info->height),
};
dst_rect = (MetaFixed16Rectangle) {
.x = meta_fixed_16_from_int (0),
.y = meta_fixed_16_from_int (0),
.width = meta_fixed_16_from_int (crtc_config->mode->width),
.height = meta_fixed_16_from_int (crtc_config->mode->height),
.width = meta_fixed_16_from_int (crtc_mode_info->width),
.height = meta_fixed_16_from_int (crtc_mode_info->height),
};
flags = META_KMS_ASSIGN_PLANE_FLAG_NONE;
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
kms_device = meta_kms_crtc_get_device (kms_crtc);
primary_kms_plane = meta_kms_device_get_primary_plane_for (kms_device,
kms_crtc);
@@ -117,7 +140,7 @@ meta_crtc_kms_assign_primary_plane (MetaCrtc *crtc,
src_rect,
dst_rect,
flags);
meta_crtc_kms_apply_transform (crtc, plane_assignment);
meta_crtc_kms_apply_transform (crtc_kms, plane_assignment);
}
static GList *
@@ -136,7 +159,7 @@ generate_crtc_connector_list (MetaGpu *gpu,
if (assigned_crtc == crtc)
{
MetaKmsConnector *kms_connector =
meta_output_kms_get_kms_connector (output);
meta_output_kms_get_kms_connector (META_OUTPUT_KMS (output));
connectors = g_list_prepend (connectors, kms_connector);
}
@@ -146,58 +169,61 @@ generate_crtc_connector_list (MetaGpu *gpu,
}
void
meta_crtc_kms_set_mode (MetaCrtc *crtc,
meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms,
MetaKmsUpdate *kms_update)
{
MetaCrtcConfig *crtc_config = crtc->config;
MetaCrtc *crtc = META_CRTC (crtc_kms);
MetaGpu *gpu = meta_crtc_get_gpu (crtc);
GList *connectors;
drmModeModeInfo *mode;
const drmModeModeInfo *mode;
connectors = generate_crtc_connector_list (gpu, crtc);
if (connectors)
{
mode = crtc_config->mode->driver_private;
const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
MetaCrtcModeKms *crtc_mode_kms = META_CRTC_MODE_KMS (crtc_config->mode);
g_debug ("Setting CRTC (%ld) mode to %s", crtc->crtc_id, mode->name);
mode = meta_crtc_mode_kms_get_drm_mode (crtc_mode_kms);
g_debug ("Setting CRTC (%ld) mode to %s",
meta_crtc_get_id (crtc), mode->name);
}
else
{
mode = NULL;
g_debug ("Unsetting CRTC (%ld) mode", crtc->crtc_id);
g_debug ("Unsetting CRTC (%ld) mode",
meta_crtc_get_id (crtc));
}
meta_kms_update_mode_set (kms_update,
meta_crtc_kms_get_kms_crtc (crtc),
meta_crtc_kms_get_kms_crtc (crtc_kms),
g_steal_pointer (&connectors),
mode);
}
void
meta_crtc_kms_page_flip (MetaCrtc *crtc,
meta_crtc_kms_page_flip (MetaCrtcKms *crtc_kms,
const MetaKmsPageFlipFeedback *page_flip_feedback,
gpointer user_data,
MetaKmsUpdate *kms_update)
{
meta_kms_update_page_flip (kms_update,
meta_crtc_kms_get_kms_crtc (crtc),
meta_crtc_kms_get_kms_crtc (crtc_kms),
page_flip_feedback,
user_data);
}
MetaKmsCrtc *
meta_crtc_kms_get_kms_crtc (MetaCrtc *crtc)
meta_crtc_kms_get_kms_crtc (MetaCrtcKms *crtc_kms)
{
MetaCrtcKms *crtc_kms = crtc->driver_private;
return crtc_kms->kms_crtc;
}
/**
* meta_crtc_kms_get_modifiers:
* @crtc: a #MetaCrtc object that has to be a #MetaCrtcKms
* @crtc_kms: a #MetaCrtc object that has to be a #MetaCrtcKms
* @format: a DRM pixel format
*
* Returns a pointer to a #GArray containing all the supported
@@ -210,93 +236,85 @@ meta_crtc_kms_get_kms_crtc (MetaCrtc *crtc)
* supported.
*/
GArray *
meta_crtc_kms_get_modifiers (MetaCrtc *crtc,
uint32_t format)
meta_crtc_kms_get_modifiers (MetaCrtcKms *crtc_kms,
uint32_t format)
{
MetaCrtcKms *crtc_kms = crtc->driver_private;
return meta_kms_plane_get_modifiers_for_format (crtc_kms->primary_plane,
format);
}
/**
* meta_crtc_kms_copy_drm_format_list:
* @crtc: a #MetaCrtc object that has to be a #MetaCrtcKms
* @crtc_kms: a #MetaCrtc object that has to be a #MetaCrtcKms
*
* Returns a new #GArray that the caller must destroy. The array
* contains all the DRM pixel formats the CRTC supports on
* its primary plane. The array element type is uint32_t.
*/
GArray *
meta_crtc_kms_copy_drm_format_list (MetaCrtc *crtc)
meta_crtc_kms_copy_drm_format_list (MetaCrtcKms *crtc_kms)
{
MetaCrtcKms *crtc_kms = crtc->driver_private;
return meta_kms_plane_copy_drm_format_list (crtc_kms->primary_plane);
}
/**
* meta_crtc_kms_supports_format:
* @crtc: a #MetaCrtc object that has to be a #MetaCrtcKms
* @crtc_kms: a #MetaCrtcKms
* @drm_format: a DRM pixel format
*
* Returns true if the CRTC supports the format on its primary plane.
*/
gboolean
meta_crtc_kms_supports_format (MetaCrtc *crtc,
uint32_t drm_format)
meta_crtc_kms_supports_format (MetaCrtcKms *crtc_kms,
uint32_t drm_format)
{
MetaCrtcKms *crtc_kms = crtc->driver_private;
return meta_kms_plane_is_format_supported (crtc_kms->primary_plane,
drm_format);
}
MetaCrtc *
MetaCrtcKms *
meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc)
{
return g_object_get_qdata (G_OBJECT (kms_crtc), kms_crtc_crtc_kms_quark);
}
static void
meta_crtc_destroy_notify (MetaCrtc *crtc)
{
g_free (crtc->driver_private);
}
MetaCrtc *
meta_create_kms_crtc (MetaGpuKms *gpu_kms,
MetaKmsCrtc *kms_crtc)
MetaCrtcKms *
meta_crtc_kms_new (MetaGpuKms *gpu_kms,
MetaKmsCrtc *kms_crtc)
{
MetaGpu *gpu = META_GPU (gpu_kms);
MetaKmsDevice *kms_device;
MetaCrtc *crtc;
MetaCrtcKms *crtc_kms;
MetaKmsPlane *primary_plane;
kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
primary_plane = meta_kms_device_get_primary_plane_for (kms_device,
kms_crtc);
crtc = g_object_new (META_TYPE_CRTC, NULL);
crtc->gpu = gpu;
crtc->crtc_id = meta_kms_crtc_get_id (kms_crtc);
crtc->is_dirty = FALSE;
crtc->all_transforms = ALL_TRANSFORMS_MASK;
crtc_kms = g_object_new (META_TYPE_CRTC_KMS,
"id", meta_kms_crtc_get_id (kms_crtc),
"gpu", gpu,
NULL);
crtc_kms = g_new0 (MetaCrtcKms, 1);
crtc_kms->kms_crtc = kms_crtc;
crtc_kms->primary_plane = primary_plane;
crtc->driver_private = crtc_kms;
crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
if (!kms_crtc_crtc_kms_quark)
{
kms_crtc_crtc_kms_quark =
g_quark_from_static_string ("meta-kms-crtc-crtc-kms-quark");
}
g_object_set_qdata (G_OBJECT (kms_crtc), kms_crtc_crtc_kms_quark, crtc);
g_object_set_qdata (G_OBJECT (kms_crtc), kms_crtc_crtc_kms_quark, crtc_kms);
return crtc;
return crtc_kms;
}
static void
meta_crtc_kms_init (MetaCrtcKms *crtc_kms)
{
}
static void
meta_crtc_kms_class_init (MetaCrtcKmsClass *klass)
{
}

View File

@@ -31,42 +31,52 @@
#include "backends/native/meta-gpu-kms.h"
#include "backends/native/meta-kms-crtc.h"
gboolean meta_crtc_kms_is_transform_handled (MetaCrtc *crtc,
#define META_TYPE_CRTC_KMS (meta_crtc_kms_get_type ())
G_DECLARE_FINAL_TYPE (MetaCrtcKms, meta_crtc_kms,
META, CRTC_KMS,
MetaCrtc)
gpointer meta_crtc_kms_get_cursor_renderer_private (MetaCrtcKms *crtc_kms);
void meta_crtc_kms_set_cursor_renderer_private (MetaCrtcKms *crtc_kms,
gpointer cursor_renderer_private);
gboolean meta_crtc_kms_is_transform_handled (MetaCrtcKms *crtc_kms,
MetaMonitorTransform transform);
void meta_crtc_kms_apply_transform (MetaCrtc *crtc,
void meta_crtc_kms_apply_transform (MetaCrtcKms *crtc_kms,
MetaKmsPlaneAssignment *kms_plane_assignment);
void meta_crtc_kms_assign_primary_plane (MetaCrtc *crtc,
void meta_crtc_kms_assign_primary_plane (MetaCrtcKms *crtc_kms,
uint32_t fb_id,
MetaKmsUpdate *kms_update);
void meta_crtc_kms_set_mode (MetaCrtc *crtc,
void meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms,
MetaKmsUpdate *kms_update);
void meta_crtc_kms_page_flip (MetaCrtc *crtc,
void meta_crtc_kms_page_flip (MetaCrtcKms *crtc_kms,
const MetaKmsPageFlipFeedback *page_flip_feedback,
gpointer user_data,
MetaKmsUpdate *kms_update);
void meta_crtc_kms_set_is_underscanning (MetaCrtc *crtc,
gboolean is_underscanning);
void meta_crtc_kms_set_is_underscanning (MetaCrtcKms *crtc_kms,
gboolean is_underscanning);
MetaKmsCrtc * meta_crtc_kms_get_kms_crtc (MetaCrtc *crtc);
MetaKmsCrtc * meta_crtc_kms_get_kms_crtc (MetaCrtcKms *crtc_kms);
GArray * meta_crtc_kms_get_modifiers (MetaCrtc *crtc,
uint32_t format);
GArray * meta_crtc_kms_get_modifiers (MetaCrtcKms *crtc_kms,
uint32_t format);
GArray *
meta_crtc_kms_copy_drm_format_list (MetaCrtc *crtc);
meta_crtc_kms_copy_drm_format_list (MetaCrtcKms *crtc_kms);
gboolean
meta_crtc_kms_supports_format (MetaCrtc *crtc,
uint32_t drm_format);
meta_crtc_kms_supports_format (MetaCrtcKms *crtc_kms,
uint32_t drm_format);
MetaCrtc * meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc);
MetaCrtcKms * meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc);
MetaCrtc * meta_create_kms_crtc (MetaGpuKms *gpu_kms,
MetaCrtcKms * meta_crtc_kms_new (MetaGpuKms *gpu_kms,
MetaKmsCrtc *kms_crtc);
#endif /* META_CRTC_KMS_H */

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2017-2020 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include "backends/native/meta-crtc-mode-kms.h"
#include "backends/native/meta-kms-utils.h"
struct _MetaCrtcModeKms
{
MetaCrtcMode parent;
drmModeModeInfo *drm_mode;
};
G_DEFINE_TYPE (MetaCrtcModeKms, meta_crtc_mode_kms,
META_TYPE_CRTC_MODE)
const drmModeModeInfo *
meta_crtc_mode_kms_get_drm_mode (MetaCrtcModeKms *mode_kms)
{
return mode_kms->drm_mode;
}
MetaCrtcModeKms *
meta_crtc_mode_kms_new (const drmModeModeInfo *drm_mode,
uint64_t id)
{
g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL;
g_autofree char *crtc_mode_name = NULL;
MetaCrtcModeKms *mode_kms;
crtc_mode_info = meta_crtc_mode_info_new ();
crtc_mode_info->width = drm_mode->hdisplay;
crtc_mode_info->height = drm_mode->vdisplay;
crtc_mode_info->flags = drm_mode->flags;
crtc_mode_info->refresh_rate =
meta_calculate_drm_mode_refresh_rate (drm_mode);
crtc_mode_name = g_strndup (drm_mode->name, DRM_DISPLAY_MODE_LEN);
mode_kms = g_object_new (META_TYPE_CRTC_MODE_KMS,
"id", id,
"name", crtc_mode_name,
"info", crtc_mode_info,
NULL);
mode_kms->drm_mode = g_slice_dup (drmModeModeInfo, drm_mode);
return mode_kms;
}
static void
meta_crtc_mode_kms_finalize (GObject *object)
{
MetaCrtcModeKms *mode_kms = META_CRTC_MODE_KMS (object);
g_slice_free (drmModeModeInfo, mode_kms->drm_mode);
G_OBJECT_CLASS (meta_crtc_mode_kms_parent_class)->finalize (object);
}
static void
meta_crtc_mode_kms_init (MetaCrtcModeKms *mode_kms)
{
}
static void
meta_crtc_mode_kms_class_init (MetaCrtcModeKmsClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_crtc_mode_kms_finalize;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2017-2020 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_CRTC_MODE_KMS_H
#define META_CRTC_MODE_KMS_H
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "backends/meta-crtc-mode.h"
#define META_TYPE_CRTC_MODE_KMS (meta_crtc_mode_kms_get_type ())
G_DECLARE_FINAL_TYPE (MetaCrtcModeKms, meta_crtc_mode_kms,
META, CRTC_MODE_KMS,
MetaCrtcMode)
const drmModeModeInfo * meta_crtc_mode_kms_get_drm_mode (MetaCrtcModeKms *crtc_mode_kms);
MetaCrtcModeKms * meta_crtc_mode_kms_new (const drmModeModeInfo *drm_mode,
uint64_t id);
#endif /* META_CRTC_MODE_KMS_H */

View File

@@ -251,13 +251,14 @@ calculate_crtc_cursor_hotspot (MetaCursorSprite *cursor_sprite,
static void
set_crtc_cursor (MetaCursorRendererNative *native,
MetaKmsUpdate *kms_update,
MetaCrtc *crtc,
MetaCrtcKms *crtc_kms,
int x,
int y,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
MetaCrtc *crtc = META_CRTC (crtc_kms);
MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite);
MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data =
@@ -272,6 +273,7 @@ set_crtc_cursor (MetaCursorRendererNative *native,
int cursor_width, cursor_height;
MetaFixed16Rectangle src_rect;
MetaFixed16Rectangle dst_rect;
struct gbm_bo *crtc_bo;
MetaKmsAssignPlaneFlag flags;
int cursor_hotspot_x;
int cursor_hotspot_y;
@@ -282,7 +284,7 @@ set_crtc_cursor (MetaCursorRendererNative *native,
else
bo = get_active_cursor_sprite_gbm_bo (cursor_gpu_state);
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
kms_device = meta_kms_crtc_get_device (kms_crtc);
cursor_plane = meta_kms_device_get_cursor_plane_for (kms_device, kms_crtc);
g_return_if_fail (cursor_plane);
@@ -305,7 +307,8 @@ set_crtc_cursor (MetaCursorRendererNative *native,
};
flags = META_KMS_ASSIGN_PLANE_FLAG_NONE;
if (!priv->hw_state_invalidated && bo == crtc->cursor_renderer_private)
crtc_bo = meta_crtc_kms_get_cursor_renderer_private (crtc_kms);
if (!priv->hw_state_invalidated && bo == crtc_bo)
flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED;
plane_assignment = meta_kms_update_assign_plane (kms_update,
@@ -323,7 +326,7 @@ set_crtc_cursor (MetaCursorRendererNative *native,
cursor_hotspot_x,
cursor_hotspot_y);
crtc->cursor_renderer_private = bo;
meta_crtc_kms_set_cursor_renderer_private (crtc_kms, bo);
if (cursor_gpu_state->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
{
@@ -336,25 +339,27 @@ set_crtc_cursor (MetaCursorRendererNative *native,
static void
unset_crtc_cursor (MetaCursorRendererNative *native,
MetaKmsUpdate *kms_update,
MetaCrtc *crtc)
MetaCrtcKms *crtc_kms)
{
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
MetaKmsPlane *cursor_plane;
struct gbm_bo *crtc_bo;
if (!priv->hw_state_invalidated && !crtc->cursor_renderer_private)
crtc_bo = meta_crtc_kms_get_cursor_renderer_private (crtc_kms);
if (!priv->hw_state_invalidated && !crtc_bo)
return;
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
kms_device = meta_kms_crtc_get_device (kms_crtc);
cursor_plane = meta_kms_device_get_cursor_plane_for (kms_device, kms_crtc);
if (cursor_plane)
meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane);
crtc->cursor_renderer_private = NULL;
meta_crtc_kms_set_cursor_renderer_private (crtc_kms, NULL);
}
static float
@@ -397,6 +402,7 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
MetaCrtc *crtc;
MetaMonitorTransform transform;
const MetaCrtcModeInfo *crtc_mode_info;
graphene_rect_t scaled_crtc_rect;
float scale;
int crtc_x, crtc_y;
@@ -415,15 +421,17 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
transform,
&crtc_x, &crtc_y);
crtc_mode_info = meta_crtc_mode_get_info (monitor_crtc_mode->crtc_mode);
if (meta_monitor_transform_is_rotated (transform))
{
crtc_width = monitor_crtc_mode->crtc_mode->height;
crtc_height = monitor_crtc_mode->crtc_mode->width;
crtc_width = crtc_mode_info->height;
crtc_height = crtc_mode_info->width;
}
else
{
crtc_width = monitor_crtc_mode->crtc_mode->width;
crtc_height = monitor_crtc_mode->crtc_mode->height;
crtc_width = crtc_mode_info->width;
crtc_height = crtc_mode_info->height;
}
scaled_crtc_rect = (graphene_rect_t) {
@@ -474,13 +482,13 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
inverted_transform = meta_monitor_transform_invert (transform);
meta_rectangle_transform (&cursor_rect,
inverted_transform,
monitor_crtc_mode->crtc_mode->width,
monitor_crtc_mode->crtc_mode->height,
crtc_mode_info->width,
crtc_mode_info->height,
&cursor_rect);
set_crtc_cursor (data->in_cursor_renderer_native,
data->in_kms_update,
crtc,
META_CRTC_KMS (crtc),
cursor_rect.x,
cursor_rect.y,
data->in_cursor_sprite);
@@ -491,7 +499,7 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
{
unset_crtc_cursor (data->in_cursor_renderer_native,
data->in_kms_update,
crtc);
META_CRTC_KMS (crtc));
}
return TRUE;
@@ -501,7 +509,8 @@ static void
disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc,
const GError *error)
{
MetaCrtc *crtc = meta_crtc_kms_from_kms_crtc (kms_crtc);
MetaCrtcKms *crtc_kms = meta_crtc_kms_from_kms_crtc (kms_crtc);
MetaCrtc *crtc = META_CRTC (crtc_kms);
MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data =
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
@@ -691,7 +700,8 @@ has_cursor_plane (MetaLogicalMonitor *logical_monitor,
gpointer user_data)
{
gboolean *has_cursor_planes = user_data;
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
*has_cursor_planes &= !!meta_kms_device_get_cursor_plane_for (kms_device,
@@ -1049,10 +1059,12 @@ unset_crtc_cursor_renderer_privates (MetaGpu *gpu,
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
{
MetaCrtc *crtc = l->data;
MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data);
struct gbm_bo *crtc_bo;
if (bo == crtc->cursor_renderer_private)
crtc->cursor_renderer_private = NULL;
crtc_bo = meta_crtc_kms_get_cursor_renderer_private (crtc_kms);
if (bo == crtc_bo)
meta_crtc_kms_set_cursor_renderer_private (crtc_kms, NULL);
}
}
@@ -1719,8 +1731,9 @@ meta_cursor_renderer_native_new (MetaBackend *backend)
MetaCursorRendererNative *cursor_renderer_native;
MetaCursorRendererNativePrivate *priv;
cursor_renderer_native =
g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL);
cursor_renderer_native = g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE,
"backend", backend,
NULL);
priv =
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);

View File

@@ -38,6 +38,7 @@
#include "backends/meta-output.h"
#include "backends/native/meta-backend-native.h"
#include "backends/native/meta-crtc-kms.h"
#include "backends/native/meta-crtc-mode-kms.h"
#include "backends/native/meta-kms-connector.h"
#include "backends/native/meta-kms-device.h"
#include "backends/native/meta-kms-update.h"
@@ -232,13 +233,28 @@ meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
uint64_t state,
MetaKmsUpdate *kms_update)
{
MetaGpu *gpu = META_GPU (gpu_kms);
GList *l;
for (l = meta_gpu_get_outputs (META_GPU (gpu_kms)); l; l = l->next)
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
{
MetaOutput *output = l->data;
meta_output_kms_set_power_save_mode (output, state, kms_update);
meta_output_kms_set_power_save_mode (META_OUTPUT_KMS (output),
state, kms_update);
}
if (state != META_POWER_SAVE_ON)
{
/* Turn off CRTCs for DPMS */
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
{
MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data);
meta_kms_update_mode_set (kms_update,
meta_crtc_kms_get_kms_crtc (crtc_kms),
NULL, NULL);
}
}
}
@@ -264,15 +280,12 @@ static int
compare_outputs (gconstpointer one,
gconstpointer two)
{
const MetaOutput *o_one = one, *o_two = two;
MetaOutput *o_one = (MetaOutput *) one;
MetaOutput *o_two = (MetaOutput *) two;
const MetaOutputInfo *output_info_one = meta_output_get_info (o_one);
const MetaOutputInfo *output_info_two = meta_output_get_info (o_two);
return strcmp (o_one->name, o_two->name);
}
static void
meta_crtc_mode_destroy_notify (MetaCrtcMode *mode)
{
g_slice_free (drmModeModeInfo, mode->driver_private);
return strcmp (output_info_one->name, output_info_two->name);
}
gboolean
@@ -325,35 +338,17 @@ meta_gpu_kms_get_mode_from_drm_mode (MetaGpuKms *gpu_kms,
for (l = meta_gpu_get_modes (gpu); l; l = l->next)
{
MetaCrtcMode *mode = l->data;
MetaCrtcModeKms *crtc_mode_kms = l->data;
if (meta_drm_mode_equal (drm_mode, mode->driver_private))
return mode;
if (meta_drm_mode_equal (drm_mode,
meta_crtc_mode_kms_get_drm_mode (crtc_mode_kms)))
return META_CRTC_MODE (crtc_mode_kms);
}
g_assert_not_reached ();
return NULL;
}
static MetaCrtcMode *
create_mode (const drmModeModeInfo *drm_mode,
long mode_id)
{
MetaCrtcMode *mode;
mode = g_object_new (META_TYPE_CRTC_MODE, NULL);
mode->mode_id = mode_id;
mode->name = g_strndup (drm_mode->name, DRM_DISPLAY_MODE_LEN);
mode->width = drm_mode->hdisplay;
mode->height = drm_mode->vdisplay;
mode->flags = drm_mode->flags;
mode->refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
mode->driver_private = g_slice_dup (drmModeModeInfo, drm_mode);
mode->driver_notify = (GDestroyNotify) meta_crtc_mode_destroy_notify;
return mode;
}
static MetaOutput *
find_output_by_connector_id (GList *outputs,
uint32_t connector_id)
@@ -364,7 +359,8 @@ find_output_by_connector_id (GList *outputs,
{
MetaOutput *output = l->data;
if (meta_output_kms_get_connector_id (output) == connector_id)
if (meta_output_kms_get_connector_id (META_OUTPUT_KMS (output)) ==
connector_id)
return output;
}
@@ -388,15 +384,9 @@ setup_output_clones (MetaGpu *gpu)
if (other_output == output)
continue;
if (meta_output_kms_can_clone (output, other_output))
{
output->n_possible_clones++;
output->possible_clones = g_renew (MetaOutput *,
output->possible_clones,
output->n_possible_clones);
output->possible_clones[output->n_possible_clones - 1] =
other_output;
}
if (meta_output_kms_can_clone (META_OUTPUT_KMS (output),
META_OUTPUT_KMS (other_output)))
meta_output_add_possible_clone (output, other_output);
}
}
}
@@ -436,9 +426,9 @@ init_modes (MetaGpuKms *gpu_kms)
mode_id = 0;
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &drm_mode))
{
MetaCrtcMode *mode;
MetaCrtcModeKms *mode;
mode = create_mode (drm_mode, (long) mode_id);
mode = meta_crtc_mode_kms_new (drm_mode, (long) mode_id);
modes = g_list_append (modes, mode);
mode_id++;
@@ -448,9 +438,10 @@ init_modes (MetaGpuKms *gpu_kms)
for (i = 0; i < G_N_ELEMENTS (meta_default_landscape_drm_mode_infos); i++)
{
MetaCrtcMode *mode;
MetaCrtcModeKms *mode;
mode = create_mode (&meta_default_landscape_drm_mode_infos[i], mode_id);
mode = meta_crtc_mode_kms_new (&meta_default_landscape_drm_mode_infos[i],
mode_id);
modes = g_list_append (modes, mode);
mode_id++;
@@ -458,9 +449,10 @@ init_modes (MetaGpuKms *gpu_kms)
for (i = 0; i < G_N_ELEMENTS (meta_default_portrait_drm_mode_infos); i++)
{
MetaCrtcMode *mode;
MetaCrtcModeKms *mode;
mode = create_mode (&meta_default_portrait_drm_mode_infos[i], mode_id);
mode = meta_crtc_mode_kms_new (&meta_default_portrait_drm_mode_infos[i],
mode_id);
modes = g_list_append (modes, mode);
mode_id++;
@@ -482,11 +474,11 @@ init_crtcs (MetaGpuKms *gpu_kms)
for (l = meta_kms_device_get_crtcs (kms_device); l; l = l->next)
{
MetaKmsCrtc *kms_crtc = l->data;
MetaCrtc *crtc;
MetaCrtcKms *crtc_kms;
crtc = meta_create_kms_crtc (gpu_kms, kms_crtc);
crtc_kms = meta_crtc_kms_new (gpu_kms, kms_crtc);
crtcs = g_list_append (crtcs, crtc);
crtcs = g_list_append (crtcs, crtc_kms);
}
meta_gpu_take_crtcs (gpu, crtcs);
@@ -519,7 +511,7 @@ init_outputs (MetaGpuKms *gpu_kms)
{
MetaKmsConnector *kms_connector = l->data;
const MetaKmsConnectorState *connector_state;
MetaOutput *output;
MetaOutputKms *output_kms;
MetaOutput *old_output;
GError *error = NULL;
@@ -530,18 +522,18 @@ init_outputs (MetaGpuKms *gpu_kms)
old_output =
find_output_by_connector_id (old_outputs,
meta_kms_connector_get_id (kms_connector));
output = meta_create_kms_output (gpu_kms,
kms_connector,
old_output,
&error);
if (!output)
output_kms = meta_output_kms_new (gpu_kms,
kms_connector,
old_output,
&error);
if (!output_kms)
{
g_warning ("Failed to create KMS output: %s", error->message);
g_error_free (error);
}
else
{
outputs = g_list_prepend (outputs, output);
outputs = g_list_prepend (outputs, output_kms);
}
}

View File

@@ -69,6 +69,7 @@ meta_input_device_native_finalize (GObject *object)
meta_input_device_native_release_touch_slots (device_evdev,
g_get_monotonic_time ());
g_clear_pointer (&device_evdev->touches, g_hash_table_unref);
backend = clutter_get_default_backend ();
seat = clutter_backend_get_default_seat (backend);

View File

@@ -21,6 +21,7 @@
#include "config.h"
#include "backends/meta-keymap-utils.h"
#include "backends/native/meta-keymap-native.h"
#include "backends/native/meta-seat-native.h"
@@ -111,7 +112,7 @@ meta_keymap_native_init (MetaKeymapNative *keymap)
names.variant = option_xkb_variant;
names.options = option_xkb_options;
ctx = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
ctx = meta_create_xkb_context ();
g_assert (ctx);
keymap->keymap = xkb_keymap_new_from_names (ctx, &names, 0);
xkb_context_unref (ctx);

View File

@@ -208,10 +208,10 @@ meta_kms_update_unassign_plane (MetaKmsUpdate *update,
}
void
meta_kms_update_mode_set (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
GList *connectors,
drmModeModeInfo *drm_mode)
meta_kms_update_mode_set (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
GList *connectors,
const drmModeModeInfo *drm_mode)
{
MetaKmsModeSet *mode_set;

View File

@@ -79,10 +79,10 @@ MetaKmsUpdate * meta_kms_update_new (void);
void meta_kms_update_free (MetaKmsUpdate *update);
void meta_kms_update_mode_set (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
GList *connectors,
drmModeModeInfo *drm_mode);
void meta_kms_update_mode_set (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
GList *connectors,
const drmModeModeInfo *drm_mode);
MetaKmsPlaneAssignment * meta_kms_update_assign_plane (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,

View File

@@ -95,7 +95,7 @@ static GBytes *
meta_monitor_manager_kms_read_edid (MetaMonitorManager *manager,
MetaOutput *output)
{
return meta_output_kms_read_edid (output);
return meta_output_kms_read_edid (META_OUTPUT_KMS (output));
}
static void
@@ -169,25 +169,41 @@ meta_monitor_manager_kms_ensure_initial_config (MetaMonitorManager *manager)
}
static void
apply_crtc_assignments (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
apply_crtc_assignments (MetaMonitorManager *manager,
MetaCrtcAssignment **crtcs,
unsigned int n_crtcs,
MetaOutputAssignment **outputs,
unsigned int n_outputs)
{
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
g_autoptr (GList) to_configure_outputs = NULL;
g_autoptr (GList) to_configure_crtcs = NULL;
unsigned i;
GList *gpus;
GList *l;
gpus = meta_backend_get_gpus (backend);
for (l = gpus; l; l = l->next)
{
MetaGpu *gpu = l->data;
GList *crtcs;
GList *outputs;
outputs = g_list_copy (meta_gpu_get_outputs (gpu));
to_configure_outputs = g_list_concat (to_configure_outputs, outputs);
crtcs = g_list_copy (meta_gpu_get_crtcs (gpu));
to_configure_crtcs = g_list_concat (to_configure_crtcs, crtcs);
}
for (i = 0; i < n_crtcs; i++)
{
MetaCrtcInfo *crtc_info = crtcs[i];
MetaCrtc *crtc = crtc_info->crtc;
MetaCrtcAssignment *crtc_assignment = crtcs[i];
MetaCrtc *crtc = crtc_assignment->crtc;
crtc->is_dirty = TRUE;
to_configure_crtcs = g_list_remove (to_configure_crtcs, crtc);
if (crtc_info->mode == NULL)
if (crtc_assignment->mode == NULL)
{
meta_crtc_unset_config (crtc);
}
@@ -196,71 +212,33 @@ apply_crtc_assignments (MetaMonitorManager *manager,
unsigned int j;
meta_crtc_set_config (crtc,
&crtc_info->layout,
crtc_info->mode,
crtc_info->transform);
&crtc_assignment->layout,
crtc_assignment->mode,
crtc_assignment->transform);
for (j = 0; j < crtc_info->outputs->len; j++)
for (j = 0; j < crtc_assignment->outputs->len; j++)
{
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
MetaOutput *output = g_ptr_array_index (crtc_assignment->outputs,
j);
MetaOutputAssignment *output_assignment;
output->is_dirty = TRUE;
meta_output_assign_crtc (output, crtc);
to_configure_outputs = g_list_remove (to_configure_outputs,
output);
output_assignment = meta_find_output_assignment (outputs,
n_outputs,
output);
meta_output_assign_crtc (output, crtc, output_assignment);
}
}
}
/* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE,
because they weren't seen in the first loop) */
gpus = meta_backend_get_gpus (backend);
for (l = gpus; l; l = l->next)
{
MetaGpu *gpu = l->data;
GList *k;
for (k = meta_gpu_get_crtcs (gpu); k; k = k->next)
{
MetaCrtc *crtc = k->data;
if (crtc->is_dirty)
{
crtc->is_dirty = FALSE;
continue;
}
meta_crtc_unset_config (crtc);
}
}
for (i = 0; i < n_outputs; i++)
{
MetaOutputInfo *output_info = outputs[i];
MetaOutput *output = output_info->output;
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
output->is_underscanning = output_info->is_underscanning;
}
/* Disable outputs not mentioned in the list */
for (l = gpus; l; l = l->next)
{
MetaGpu *gpu = l->data;
GList *k;
for (k = meta_gpu_get_outputs (gpu); k; k = k->next)
{
MetaOutput *output = k->data;
if (output->is_dirty)
{
output->is_dirty = FALSE;
continue;
}
meta_output_unassign_crtc (output);
output->is_primary = FALSE;
}
}
g_list_foreach (to_configure_crtcs,
(GFunc) meta_crtc_unset_config,
NULL);
g_list_foreach (to_configure_outputs,
(GFunc) meta_output_unassign_crtc,
NULL);
}
static void
@@ -298,8 +276,8 @@ meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager *manager
MetaMonitorsConfigMethod method,
GError **error)
{
GPtrArray *crtc_infos;
GPtrArray *output_infos;
GPtrArray *crtc_assignments;
GPtrArray *output_assignments;
if (!config)
{
@@ -310,25 +288,26 @@ meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager *manager
}
if (!meta_monitor_config_manager_assign (manager, config,
&crtc_infos, &output_infos,
&crtc_assignments,
&output_assignments,
error))
return FALSE;
if (method == META_MONITORS_CONFIG_METHOD_VERIFY)
{
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
g_ptr_array_free (crtc_assignments, TRUE);
g_ptr_array_free (output_assignments, TRUE);
return TRUE;
}
apply_crtc_assignments (manager,
(MetaCrtcInfo **) crtc_infos->pdata,
crtc_infos->len,
(MetaOutputInfo **) output_infos->pdata,
output_infos->len);
(MetaCrtcAssignment **) crtc_assignments->pdata,
crtc_assignments->len,
(MetaOutputAssignment **) output_assignments->pdata,
output_assignments->len);
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
g_ptr_array_free (crtc_assignments, TRUE);
g_ptr_array_free (output_assignments, TRUE);
update_screen_size (manager, config);
meta_monitor_manager_rebuild (manager, config);
@@ -347,7 +326,7 @@ meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager *manager,
MetaKmsCrtc *kms_crtc;
const MetaKmsCrtcState *crtc_state;
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
crtc_state = meta_kms_crtc_get_current_state (kms_crtc);
*size = crtc_state->gamma.size;
@@ -435,11 +414,12 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
gamma_ramp_string = generate_gamma_ramp_string (size, red, green, blue);
g_debug ("Setting CRTC (%ld) gamma to %s", crtc->crtc_id, gamma_ramp_string);
g_debug ("Setting CRTC (%ld) gamma to %s",
meta_crtc_get_id (crtc), gamma_ramp_string);
kms_update = meta_kms_ensure_pending_update (kms);
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
meta_kms_crtc_set_gamma (kms_crtc, kms_update,
size, red, green, blue);
@@ -507,7 +487,7 @@ meta_monitor_manager_kms_is_transform_handled (MetaMonitorManager *manager,
MetaCrtc *crtc,
MetaMonitorTransform transform)
{
return meta_crtc_kms_is_transform_handled (crtc, transform);
return meta_crtc_kms_is_transform_handled (META_CRTC_KMS (crtc), transform);
}
static float

View File

@@ -32,6 +32,7 @@
#include "backends/native/meta-kms-connector.h"
#include "backends/native/meta-kms-utils.h"
#include "backends/native/meta-crtc-kms.h"
#include "backends/native/meta-crtc-mode-kms.h"
#include "meta-default-modes.h"
@@ -44,33 +45,37 @@ typedef struct _MetaOutputKms
MetaKmsConnector *kms_connector;
} MetaOutputKms;
MetaKmsConnector *
meta_output_kms_get_kms_connector (MetaOutput *output)
{
MetaOutputKms *output_kms = output->driver_private;
G_DEFINE_TYPE (MetaOutputKms, meta_output_kms, META_TYPE_OUTPUT)
MetaKmsConnector *
meta_output_kms_get_kms_connector (MetaOutputKms *output_kms)
{
return output_kms->kms_connector;
}
void
meta_output_kms_set_underscan (MetaOutput *output,
meta_output_kms_set_underscan (MetaOutputKms *output_kms,
MetaKmsUpdate *kms_update)
{
MetaOutputKms *output_kms = output->driver_private;
MetaOutput *output = META_OUTPUT (output_kms);
const MetaOutputInfo *output_info = meta_output_get_info (output);
if (!output->supports_underscanning)
if (!output_info->supports_underscanning)
return;
if (output->is_underscanning)
if (meta_output_is_underscanning (output))
{
MetaCrtc *crtc;
MetaCrtcConfig *crtc_config;
const MetaCrtcConfig *crtc_config;
const MetaCrtcModeInfo *crtc_mode_info;
uint64_t hborder, vborder;
crtc = meta_output_get_assigned_crtc (output);
crtc_config = crtc->config;
hborder = MIN (128, (uint64_t) round (crtc_config->mode->width * 0.05));
vborder = MIN (128, (uint64_t) round (crtc_config->mode->height * 0.05));
crtc_config = meta_crtc_get_config (crtc);
crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode);
hborder = MIN (128, (uint64_t) round (crtc_mode_info->width * 0.05));
vborder = MIN (128, (uint64_t) round (crtc_mode_info->height * 0.05));
g_debug ("Setting underscan of connector %s to %" G_GUINT64_FORMAT " x %" G_GUINT64_FORMAT,
meta_kms_connector_get_name (output_kms->kms_connector),
@@ -92,20 +97,16 @@ meta_output_kms_set_underscan (MetaOutput *output,
}
uint32_t
meta_output_kms_get_connector_id (MetaOutput *output)
meta_output_kms_get_connector_id (MetaOutputKms *output_kms)
{
MetaOutputKms *output_kms = output->driver_private;
return meta_kms_connector_get_id (output_kms->kms_connector);
}
void
meta_output_kms_set_power_save_mode (MetaOutput *output,
meta_output_kms_set_power_save_mode (MetaOutputKms *output_kms,
uint64_t dpms_state,
MetaKmsUpdate *kms_update)
{
MetaOutputKms *output_kms = output->driver_private;
g_debug ("Setting DPMS state of connector %s to %" G_GUINT64_FORMAT,
meta_kms_connector_get_name (output_kms->kms_connector),
dpms_state);
@@ -116,20 +117,16 @@ meta_output_kms_set_power_save_mode (MetaOutput *output,
}
gboolean
meta_output_kms_can_clone (MetaOutput *output,
MetaOutput *other_output)
meta_output_kms_can_clone (MetaOutputKms *output_kms,
MetaOutputKms *other_output_kms)
{
MetaOutputKms *output_kms = output->driver_private;
MetaOutputKms *other_output_kms = other_output->driver_private;
return meta_kms_connector_can_clone (output_kms->kms_connector,
other_output_kms->kms_connector);
}
GBytes *
meta_output_kms_read_edid (MetaOutput *output)
meta_output_kms_read_edid (MetaOutputKms *output_kms)
{
MetaOutputKms *output_kms = output->driver_private;
const MetaKmsConnectorState *connector_state;
GBytes *edid_data;
@@ -143,18 +140,8 @@ meta_output_kms_read_edid (MetaOutput *output)
}
static void
meta_output_destroy_notify (MetaOutput *output)
{
MetaOutputKms *output_kms;
output_kms = output->driver_private;
g_slice_free (MetaOutputKms, output_kms);
}
static void
add_common_modes (MetaOutput *output,
MetaGpuKms *gpu_kms)
add_common_modes (MetaOutputInfo *output_info,
MetaGpuKms *gpu_kms)
{
const drmModeModeInfo *drm_mode;
MetaCrtcMode *crtc_mode;
@@ -165,9 +152,12 @@ add_common_modes (MetaOutput *output,
unsigned max_vdisplay = 0;
float max_refresh_rate = 0.0;
for (i = 0; i < output->n_modes; i++)
for (i = 0; i < output_info->n_modes; i++)
{
drm_mode = output->modes[i]->driver_private;
MetaCrtcMode *crtc_mode = output_info->modes[i];
MetaCrtcModeKms *crtc_mode_kms = META_CRTC_MODE_KMS (crtc_mode);
drm_mode = meta_crtc_mode_kms_get_drm_mode (crtc_mode_kms);
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
max_hdisplay = MAX (max_hdisplay, drm_mode->hdisplay);
max_vdisplay = MAX (max_vdisplay, drm_mode->vdisplay);
@@ -211,11 +201,11 @@ add_common_modes (MetaOutput *output,
}
}
output->modes = g_renew (MetaCrtcMode *, output->modes,
output->n_modes + array->len);
memcpy (output->modes + output->n_modes, array->pdata,
output_info->modes = g_renew (MetaCrtcMode *, output_info->modes,
output_info->n_modes + array->len);
memcpy (output_info->modes + output_info->n_modes, array->pdata,
array->len * sizeof (MetaCrtcMode *));
output->n_modes += array->len;
output_info->n_modes += array->len;
g_ptr_array_free (array, TRUE);
}
@@ -224,135 +214,148 @@ static int
compare_modes (const void *one,
const void *two)
{
MetaCrtcMode *a = *(MetaCrtcMode **) one;
MetaCrtcMode *b = *(MetaCrtcMode **) two;
MetaCrtcMode *crtc_mode_one = *(MetaCrtcMode **) one;
MetaCrtcMode *crtc_mode_two = *(MetaCrtcMode **) two;
const MetaCrtcModeInfo *crtc_mode_info_one =
meta_crtc_mode_get_info (crtc_mode_one);
const MetaCrtcModeInfo *crtc_mode_info_two =
meta_crtc_mode_get_info (crtc_mode_two);
if (a->width != b->width)
return a->width > b->width ? -1 : 1;
if (a->height != b->height)
return a->height > b->height ? -1 : 1;
if (a->refresh_rate != b->refresh_rate)
return a->refresh_rate > b->refresh_rate ? -1 : 1;
if (crtc_mode_info_one->width != crtc_mode_info_two->width)
return crtc_mode_info_one->width > crtc_mode_info_two->width ? -1 : 1;
if (crtc_mode_info_one->height != crtc_mode_info_two->height)
return crtc_mode_info_one->height > crtc_mode_info_two->height ? -1 : 1;
if (crtc_mode_info_one->refresh_rate != crtc_mode_info_two->refresh_rate)
return (crtc_mode_info_one->refresh_rate > crtc_mode_info_two->refresh_rate
? -1 : 1);
return g_strcmp0 (b->name, a->name);
return g_strcmp0 (meta_crtc_mode_get_name (crtc_mode_one),
meta_crtc_mode_get_name (crtc_mode_two));
}
static gboolean
init_output_modes (MetaOutput *output,
MetaGpuKms *gpu_kms,
GError **error)
init_output_modes (MetaOutputInfo *output_info,
MetaGpuKms *gpu_kms,
MetaKmsConnector *kms_connector,
GError **error)
{
MetaOutputKms *output_kms = output->driver_private;
const MetaKmsConnectorState *connector_state;
int i;
connector_state =
meta_kms_connector_get_current_state (output_kms->kms_connector);
connector_state = meta_kms_connector_get_current_state (kms_connector);
output->preferred_mode = NULL;
output_info->preferred_mode = NULL;
output->n_modes = connector_state->n_modes;
output->modes = g_new0 (MetaCrtcMode *, output->n_modes);
output_info->n_modes = connector_state->n_modes;
output_info->modes = g_new0 (MetaCrtcMode *, output_info->n_modes);
for (i = 0; i < connector_state->n_modes; i++)
{
drmModeModeInfo *drm_mode = &connector_state->modes[i];
MetaCrtcMode *crtc_mode;
crtc_mode = meta_gpu_kms_get_mode_from_drm_mode (gpu_kms, drm_mode);
output->modes[i] = crtc_mode;
output_info->modes[i] = crtc_mode;
if (drm_mode->type & DRM_MODE_TYPE_PREFERRED)
output->preferred_mode = output->modes[i];
output_info->preferred_mode = output_info->modes[i];
}
/* FIXME: MSC feature bit? */
/* Presume that if the output supports scaling, then we have
* a panel fitter capable of adjusting any mode to suit.
*/
if (connector_state->has_scaling)
add_common_modes (output, gpu_kms);
add_common_modes (output_info, gpu_kms);
if (!output->modes)
if (!output_info->modes)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No modes available");
return FALSE;
}
qsort (output->modes, output->n_modes,
qsort (output_info->modes, output_info->n_modes,
sizeof (MetaCrtcMode *), compare_modes);
if (!output->preferred_mode)
output->preferred_mode = output->modes[0];
if (!output_info->preferred_mode)
output_info->preferred_mode = output_info->modes[0];
return TRUE;
}
MetaOutput *
meta_create_kms_output (MetaGpuKms *gpu_kms,
MetaKmsConnector *kms_connector,
MetaOutput *old_output,
GError **error)
MetaOutputKms *
meta_output_kms_new (MetaGpuKms *gpu_kms,
MetaKmsConnector *kms_connector,
MetaOutput *old_output,
GError **error)
{
MetaGpu *gpu = META_GPU (gpu_kms);
uint32_t connector_id;
uint32_t gpu_id;
g_autoptr (MetaOutputInfo) output_info = NULL;
MetaOutput *output;
MetaOutputKms *output_kms;
const MetaKmsConnectorState *connector_state;
uint32_t connector_id;
GArray *crtcs;
GList *l;
uint32_t gpu_id;
output = g_object_new (META_TYPE_OUTPUT, NULL);
output_kms = g_slice_new0 (MetaOutputKms);
output->driver_private = output_kms;
output->driver_notify = (GDestroyNotify) meta_output_destroy_notify;
output->gpu = gpu;
output->name = g_strdup (meta_kms_connector_get_name (kms_connector));
gpu_id = meta_gpu_kms_get_id (gpu_kms);
connector_id = meta_kms_connector_get_id (kms_connector);
output->winsys_id = ((uint64_t) gpu_id << 32) | connector_id;
output_kms->kms_connector = kms_connector;
output_info = meta_output_info_new ();
output_info->name = g_strdup (meta_kms_connector_get_name (kms_connector));
connector_state = meta_kms_connector_get_current_state (kms_connector);
output->panel_orientation_transform =
output_info->panel_orientation_transform =
connector_state->panel_orientation_transform;
if (meta_monitor_transform_is_rotated (output->panel_orientation_transform))
if (meta_monitor_transform_is_rotated (output_info->panel_orientation_transform))
{
output->width_mm = connector_state->height_mm;
output->height_mm = connector_state->width_mm;
output_info->width_mm = connector_state->height_mm;
output_info->height_mm = connector_state->width_mm;
}
else
{
output->width_mm = connector_state->width_mm;
output->height_mm = connector_state->height_mm;
output_info->width_mm = connector_state->width_mm;
output_info->height_mm = connector_state->height_mm;
}
if (!init_output_modes (output, gpu_kms, error))
{
g_object_unref (output);
return NULL;
}
if (!init_output_modes (output_info, gpu_kms, kms_connector, error))
return NULL;
crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCrtc *));
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
{
MetaCrtc *crtc = l->data;
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data);
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
uint32_t crtc_idx;
crtc_idx = meta_kms_crtc_get_idx (kms_crtc);
if (connector_state->common_possible_crtcs & (1 << crtc_idx))
g_array_append_val (crtcs, crtc);
g_array_append_val (crtcs, crtc_kms);
}
output->n_possible_crtcs = crtcs->len;
output->possible_crtcs = (MetaCrtc **) g_array_free (crtcs, FALSE);
output_info->n_possible_crtcs = crtcs->len;
output_info->possible_crtcs = (MetaCrtc **) g_array_free (crtcs, FALSE);
output_info->suggested_x = connector_state->suggested_x;
output_info->suggested_y = connector_state->suggested_y;
output_info->hotplug_mode_update = connector_state->hotplug_mode_update;
output_info->supports_underscanning =
meta_kms_connector_is_underscanning_supported (kms_connector);
meta_output_info_parse_edid (output_info, connector_state->edid_data);
output_info->connector_type = meta_kms_connector_get_connector_type (kms_connector);
output_info->tile_info = connector_state->tile_info;
output = g_object_new (META_TYPE_OUTPUT_KMS,
"id", ((uint64_t) gpu_id << 32) | connector_id,
"gpu", gpu,
"info", output_info,
NULL);
output_kms = META_OUTPUT_KMS (output);
output_kms->kms_connector = kms_connector;
if (connector_state->current_crtc_id)
{
@@ -360,9 +363,25 @@ meta_create_kms_output (MetaGpuKms *gpu_kms,
{
MetaCrtc *crtc = l->data;
if (crtc->crtc_id == connector_state->current_crtc_id)
if (meta_crtc_get_id (crtc) == connector_state->current_crtc_id)
{
meta_output_assign_crtc (output, crtc);
MetaOutputAssignment output_assignment;
if (old_output)
{
output_assignment = (MetaOutputAssignment) {
.is_primary = meta_output_is_primary (old_output),
.is_presentation = meta_output_is_presentation (old_output),
};
}
else
{
output_assignment = (MetaOutputAssignment) {
.is_primary = FALSE,
.is_presentation = FALSE,
};
}
meta_output_assign_crtc (output, crtc, &output_assignment);
break;
}
}
@@ -372,41 +391,15 @@ meta_create_kms_output (MetaGpuKms *gpu_kms,
meta_output_unassign_crtc (output);
}
if (old_output)
{
output->is_primary = old_output->is_primary;
output->is_presentation = old_output->is_presentation;
}
else
{
output->is_primary = FALSE;
output->is_presentation = FALSE;
}
output->suggested_x = connector_state->suggested_x;
output->suggested_y = connector_state->suggested_y;
output->hotplug_mode_update = connector_state->hotplug_mode_update;
output->supports_underscanning =
meta_kms_connector_is_underscanning_supported (kms_connector);
meta_output_parse_edid (output, connector_state->edid_data);
output->connector_type = meta_kms_connector_get_connector_type (kms_connector);
output->tile_info = connector_state->tile_info;
/* FIXME: backlight is a very driver specific thing unfortunately,
every DDX does its own thing, and the dumb KMS API does not include it.
For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
(one for each major HW maker, and then some).
We can't do the same because we're not root.
It might be best to leave backlight out of the story and rely on the setuid
helper in gnome-settings-daemon.
*/
output->backlight_min = 0;
output->backlight_max = 0;
output->backlight = -1;
return output;
return output_kms;
}
static void
meta_output_kms_init (MetaOutputKms *output_kms)
{
}
static void
meta_output_kms_class_init (MetaOutputKmsClass *klass)
{
}

View File

@@ -27,23 +27,28 @@
#include "backends/native/meta-gpu-kms.h"
#include "backends/native/meta-kms-types.h"
void meta_output_kms_set_power_save_mode (MetaOutput *output,
#define META_TYPE_OUTPUT_KMS (meta_output_kms_get_type ())
G_DECLARE_FINAL_TYPE (MetaOutputKms, meta_output_kms,
META, OUTPUT_KMS,
MetaOutput)
void meta_output_kms_set_power_save_mode (MetaOutputKms *output_kms,
uint64_t dpms_state,
MetaKmsUpdate *kms_update);
void meta_output_kms_set_underscan (MetaOutput *output,
void meta_output_kms_set_underscan (MetaOutputKms *output_kms,
MetaKmsUpdate *kms_update);
gboolean meta_output_kms_can_clone (MetaOutput *output,
MetaOutput *other_output);
gboolean meta_output_kms_can_clone (MetaOutputKms *output_kms,
MetaOutputKms *other_output_kms);
MetaKmsConnector * meta_output_kms_get_kms_connector (MetaOutput *output);
MetaKmsConnector * meta_output_kms_get_kms_connector (MetaOutputKms *output_kms);
uint32_t meta_output_kms_get_connector_id (MetaOutput *output);
uint32_t meta_output_kms_get_connector_id (MetaOutputKms *output_kms);
GBytes * meta_output_kms_read_edid (MetaOutput *output);
GBytes * meta_output_kms_read_edid (MetaOutputKms *output_kms);
MetaOutput * meta_create_kms_output (MetaGpuKms *gpu_kms,
MetaOutputKms * meta_output_kms_new (MetaGpuKms *gpu_kms,
MetaKmsConnector *kms_connector,
MetaOutput *old_output,
GError **error);

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