Surface buffers are created with meta_drm_buffer_new_acquire(), taking a
gbm_surface acquiring the gbm itself, and meta_drm_buffer_new_take()
that takes over ownership of a passed gbm_bo.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/798
The port to per CRTC views was incomplete; we still used the logical
monitor layout as the stage view layout, while still using one view per
CRTC.
This worked fine for most cases, e.g. regular monitors, tiled or
non-tiled, transformed or non-transformed. Where it broke, however, was
when a monitor consists of multiple CRTCs. We already have the layout a
CRTC corresponds to on the stage kept with the CRTC metadata, so use
this directly.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1170https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1199`
This is so that cogl-trace.h can start using things from cogl-macros.h,
and so that it doesn't leak cogl-config.h into the world, while exposing
it to e.g. gnome-shell so that it can make use of it as well. There is
no practical reason why we shouldn't just include cogl-trace.h via
cogl.h as we do with everything else.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1059
Create a new gbm_bo using the same given geometry, and export the new
bo's DMA buffer fd. The new bo lives as long as necessary to be used,
and reused, by PipeWire.
Unfortunately, PipeWire doesn't support modifiers properly, so use the
linear format for now. For now, a hardcoded format of DRM_FORMAT_XRGB8888
is set, so we don't need to negotiate the format with PipeWire early.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
Prior to this commit the stage was drawn separately for each logical
monitor. This allowed to draw different parts of the stage with
different transformations, e.g. with a different viewport to implement
HiDPI support.
Go even further and have one view per CRTC. This causes the stage to
e.g. draw two mirrored monitors twice, instead of using the same
framebuffer on both. This enables us to do two things: one is to support
tiled monitors and monitor mirroring using the EGLStreams backend; the
other is that it'll enable us to tie rendering directly to the CRTC it
will render for. It is also a requirement for rendering being affected
by CRTC state, such as gamma.
It'll be possible to still inhibit re-drawing of the same content
twice, but it should be implemented differently, so that it will still
be possible to implement features requiring the CRTC split.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
To make it more reliable to distinguish between values that are read
from the backend implementation (which is likely to be irrelevant for
anything but the backend implementation), split out those values (e.g.
layout).
This changes the meaning of what was MetaCrtc::rect, to a
MetaCrtcConfig::layout which is the layout the CRTC has in the global
coordinate space.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
The current API as all synchronous, so they can be made to return
feedback immediately. This will be needed for the cursor renderer which
needs to know whether it should fall back to OpenGL cursor rendering.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/930
Where possible, try to export the buffer rendered by the primary GPU as a
dmabuf and import it to the secondary GPU and turn it into a DRM FB for
scanout. If this works, we get a zero-copy path to secondary GPU outputs.
This is especially useful on virtual drivers like EVDI (used for DisplayLink
devices) which are not picky at all about what kind of FBs they can handle.
The zero-copy path is prioritised after the secondary GPU copy path, which
should avoid regressions for existing working systems. Attempting zero-copy
would have the risk of being less performant than doing the copy on the
secondary GPU. This does not affect the DisplayLink use case, because there is
no GPU in a DisplayLink device.
The zero-copy path is prioritised before the primary GPU and CPU copy paths. It
will be tried on the first frame of an output and the copy path is executed
too. If zero-copy fails, the result from the copy path will take over on that
frame. Furthermore, zero-copy will not be attemped again on that output. If
zero-copy succeeds, the copy path is de-initialized.
Zero-copy is assumed to be always preferable over the primary GPU and CPU copy
paths. Whether this is universally true remains to be seen.
This patch has one unhandled failure mode: if zero-copy path first succeeds and
then fails later, there is no fallback and the output is left frozen or black.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/810
With all the three paths this is quite a handful of code, and it was mostly
duplicated in two places. A follow-up patch would need to introduce a third
copy of it. Therefore move the code into a helper function.
There are two behavioral changes:
- The format error now prints the string code as well, because it is easy to
read.
- The g_debug() in init_dumb_fb() is removed. Did not seem useful.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/810
There will be another place where I need to release the dumb buffers but not
destroy the whole secondary_gpu_state, so extract this bit of code into a
helper.
The checks of fb_id are dropped as redundant with the check already in in
release_dumb_fb ().
https://gitlab.gnome.org/GNOME/mutter/merge_requests/810
release_dumb_fb () checks 'map' to see if anything needs freeing. Other places
are checking fb_id instead. The checks maybe redundant, but let's reset all
fields here while at it, so that all the checks work as expected.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/810
Simplify the bo freeing functions by not checking what the copy mode is. This
matches what swap_secondary_drm_fb () already does. g_clear_object () is safe
to call even if the value is already NULL.
The copy mode does not change mid-operation. If it did, this change would
ensure we still clean up everything. So this is more future-proof too.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/810
To mirror what happens in meta_onscreen_native_swap_buffers_with_damage(), warn
here too if next_fb is not NULL. This makes it clear to the reader of what the
expectations are inside this function.
Ensuring next_fb is NULL as the first thing in the function will make all error
paths equal: no longer some failures reset next_fb while others don't. Removing
such special cases should reduce surprises.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/810
Create the intermediate shadow framebuffer for use exclusively when a
shadowfb is required.
Keep the previous offscreen framebuffer is as an intermediate
framebuffer for transformations only.
This way, we can apply transformations between in-memory framebuffers
prior to blit the result to screen, and achieve acceptable performance
even with software rendering on discrete GPU.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/877
It was not the lack of forcing the shadow fb that caused slowness, but
rather due to the method the shadow fb content was copied onto the
scanout fb. With 'clutter: Use cogl_blit_framebuffer() for shadow FB'
we'll use a path that shouldn't be slow when copying onto the scanout
fb.
Also 437f6b3d59 accidentally enabled
shadow fb when using hw accelerated contexts, due to the cap being set
to 1 in majority of drivers. While the kernel documentation for the
related field says "hint to userspace to prefer shadow-fb rendering",
the name of the hint when exposed to userspace is
DRM_CAP_DUMB_PREFER_SHADOW, thus should only be taken into consideration
for dumb buffers, not rendering in general.
This reverts commit 437f6b3d59.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/818
The commit 'renderer/native: Use shadow fb on software GL if preferred'
attempted to force using a shadow fb when using llvmpipe in order to
speed up blending, but instead only did so when llvmpipe AND the drm
device explicityl asked for it.
Now instead always force it for llvmpipe and other software rendering
backends, and otherwise just query the drm device (i.e.
DRM_CAP_DUMB_PREFER_SHADOW).
https://gitlab.gnome.org/GNOME/mutter/merge_requests/807
COPY_MODE_PRIMARY has two paths, automatically chosen. For debugging purposes,
e.g. why is my DisplayLink screen slowing down the whole desktop, it will be
useful to know which copy path is taken. Debug prints are added to both when
the primary GPU copy succeeds the first time and when it fails the first time.
This is not the full truth, because theoretically the success/failure could
change every frame, but we don't want to spam the logs (even in debug mode)
every frame. In practise, it should be rare for the success or failure to ever
change. Hence, saying what happened on the first time is enough. This does
indicate if it ever changes even once, too, so we know if that unexpected thing
happens.
The debug prints are per secondary GPU since there could be several.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
When the preferred path META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU cannot
be used, as is the case for e.g. DisplayLink devices which do not actually have
a GPU, try to use the primary GPU for the copying before falling back to
read-pixels which is a CPU copy.
When the primary GPU copy works, it should be a significant performance win
over the CPU copy by avoiding stalling libmutter for the duration.
This also renames META_SHARED_FRAMEBUFFER_COPY_MODE_* because the new names are
more accurate. While the secondary GPU copy is always a GPU copy, the primary
copy might be either a CPU or a GPU copy.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
Simplify the call site a bit and make the native renderer know it should
queue mode reset itself when views have been rebuilt. This is done
partly due to more things needing to be dealt with after views have been
rebuilt.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/630
When building without EGL device support, the following compiler warning
is seen:
```
src/backends/native/meta-renderer-native.c:2637:20: warning: unused
variable ‘cogl_renderer_egl’ [-Wunused-variable]
```
Fix the warning by placing the relevant variable declarations within the
`#ifdef HAVE_EGL_DEVICE/#endif` statement.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/656
This commit introduces, and makes use of, a transactional API used for
setting up KMS state, later to be applied, potentially atomically. From
an API point of view, so is always the case, but in the current
implementation, it still uses legacy drmMode* API to apply the state
non-atomically.
The API consists of various buliding blocks:
* MetaKmsUpdate - a set of configuration changes, the higher level
handle for handing over configuration to the impl backend. It's used to
set mode, assign framebuffers to planes, queue page flips and set
connector properties.
* MetaKmsPlaneAssignment - the assignment of a framebuffer to a plane.
Currently used to map a framebuffer to the primary plane of a CRTC. In
the legacy KMS implementation, the plane assignment is used to derive
the framebuffer used for mode setting and page flipping.
This also means various high level changes:
State, excluding configuring the cursor plane and creating/destroying
DRM framebuffer handles, are applied in the end of a clutter frame, in
one go. From an API point of view, this is done atomically, but as
mentioned, only the non-atomic implementation exists so far.
From MetaRendererNative's point of view, a page flip now initially
always succeeds; the handling of EBUSY errors are done asynchronously in
the MetaKmsImpl backend (still by retrying at refresh rate, but
postponing flip callbacks instead of manipulating the frame clock).
Handling of falling back to mode setting instead of page flipping is
notified after the fact by a more precise page flip feedback API.
EGLStream based page flipping relies on the impl backend not being
atomic, as the page flipping is done in the EGLStream backend (e.g.
nvidia driver). It uses a 'custom' page flip queueing method, keeping
the EGLStream logic inside meta-renderer-native.c.
Page flip handling is moved to meta-kms-impl-device.c from
meta-gpu-kms.c. It goes via an extra idle callback before reaching
meta-renderer-native.c to make sure callbacks are invoked outside of the
impl context.
While dummy power save page flipping is kept in meta-renderer-native.c, the
EBUSY handling is moved to meta-kms-impl-simple.c. Instead of freezing the
frame clock, actual page flip callbacks are postponed until all EBUSY retries
have either succeeded or failed due to some other error than EBUSY. This
effectively inhibits new frames to be drawn, meaning we won't stall waiting on
the file descriptor for pending page flips.
https://gitlab.gnome.org/GNOME/mutter/issues/548https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
Fix the following compiler warning:
../src/backends/native/meta-renderer-native.c: In function ‘meta_renderer_native_create_view’:
/usr/include/glib-2.0/glib/gmacros.h:523:17: warning: ‘formats’ may be used uninitialized in this function [-Wmaybe-uninitialized]
523 | { if (_ptr) (cleanup) ((ParentName *) _ptr); } \
| ^
../src/backends/native/meta-renderer-native.c:773:22: note: ‘formats’ was declared here
773 | g_autoptr (GArray) formats;
| ^~~~~~~
https://gitlab.gnome.org/GNOME/mutter/merge_requests/632
Make sure to destroy the EGL surface after releasing held buffers,
otherwise we'll get the following valgrind warnings:
==24016== Invalid read of size 8
==24016== at 0x1739943F: release_buffer (platform_drm.c:73)
==24016== by 0x49AC355: meta_drm_buffer_gbm_finalize (meta-drm-buffer-gbm.c:213)
==24016== by 0x4B75B61: g_object_unref (gobject.c:3346)
==24016== by 0x49B4B41: free_current_bo (meta-renderer-native.c:991)
==24016== by 0x49B816F: meta_renderer_native_release_onscreen (meta-renderer-native.c:2971)
==24016== by 0x5209441: _cogl_onscreen_free (cogl-onscreen.c:167)
==24016== by 0x5208D81: _cogl_object_onscreen_indirect_free (cogl-onscreen.c:51)
==24016== by 0x51C8066: _cogl_object_default_unref (cogl-object.c:103)
==24016== by 0x5207989: _cogl_framebuffer_unref (cogl-framebuffer.c:1814)
==24016== by 0x51C80B1: cogl_object_unref (cogl-object.c:115)
==24016== by 0x53673C7: clutter_stage_view_dispose (clutter-stage-view.c:304)
==24016== by 0x4B75AF2: g_object_unref (gobject.c:3309)
==24016== Address 0x18e742a8 is 536 bytes inside a block of size 784 free'd
==24016== at 0x4839A0C: free (vg_replace_malloc.c:540)
==24016== by 0x17399764: dri2_drm_destroy_surface (platform_drm.c:231)
==24016== by 0x1738550A: eglDestroySurface (eglapi.c:1145)
==24016== by 0x5440286: eglDestroySurface (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0)
==24016== by 0x49613A5: meta_egl_destroy_surface (meta-egl.c:432)
==24016== by 0x49B80F9: meta_renderer_native_release_onscreen (meta-renderer-native.c:2954)
==24016== by 0x5209441: _cogl_onscreen_free (cogl-onscreen.c:167)
==24016== by 0x5208D81: _cogl_object_onscreen_indirect_free (cogl-onscreen.c:51)
==24016== by 0x51C8066: _cogl_object_default_unref (cogl-object.c:103)
==24016== by 0x5207989: _cogl_framebuffer_unref (cogl-framebuffer.c:1814)
==24016== by 0x51C80B1: cogl_object_unref (cogl-object.c:115)
==24016== by 0x53673C7: clutter_stage_view_dispose (clutter-stage-view.c:304)
==24016== Block was alloc'd at
==24016== at 0x483AB1A: calloc (vg_replace_malloc.c:762)
==24016== by 0x173997AE: dri2_drm_create_window_surface (platform_drm.c:145)
==24016== by 0x17388906: _eglCreateWindowSurfaceCommon (eglapi.c:929)
==24016== by 0x5440197: eglCreateWindowSurface (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0)
==24016== by 0x49612FF: meta_egl_create_window_surface (meta-egl.c:396)
==24016== by 0x49B752E: meta_renderer_native_create_surface_gbm (meta-renderer-native.c:2538)
==24016== by 0x49B7E6C: meta_onscreen_native_allocate (meta-renderer-native.c:2870)
==24016== by 0x49B8BCF: meta_renderer_native_create_view (meta-renderer-native.c:3387)
==24016== by 0x48D274B: meta_renderer_create_view (meta-renderer.c:78)
==24016== by 0x48D27DE: meta_renderer_rebuild_views (meta-renderer.c:111)
==24016== by 0x49BB4FB: meta_stage_native_rebuild_views (meta-stage-native.c:142)
==24016== by 0x49A733C: meta_backend_native_update_screen_size (meta-backend-native.c:517)
https://gitlab.gnome.org/GNOME/mutter/merge_requests/622
When making a new surface/context pair current, mesa may want to flush
the old context. Make sure we don't try to flush any freed memory by
unmaking a surface/context pair current before freeing it.
Not doing this results in the following valgrind warnings:
==15986== Invalid read of size 8
==15986== at 0x69A6D80: dri_flush_front_buffer (gbm_dri.c:92)
==15986== by 0x1750D458: intel_flush_front (brw_context.c:251)
==15986== by 0x1750D4BB: intel_glFlush (brw_context.c:296)
==15986== by 0x1739D8DD: dri2_make_current (egl_dri2.c:1461)
==15986== by 0x17393A3A: eglMakeCurrent (eglapi.c:869)
==15986== by 0x54381FB: InternalMakeCurrentVendor (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0)
==15986== by 0x5438515: eglMakeCurrent (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0)
==15986== by 0x522A782: _cogl_winsys_egl_make_current (cogl-winsys-egl.c:303)
==15986== by 0x49B64C8: meta_renderer_native_create_view (meta-renderer-native.c:3076)
==15986== by 0x48D26E7: meta_renderer_create_view (meta-renderer.c:78)
==15986== by 0x48D277A: meta_renderer_rebuild_views (meta-renderer.c:111)
==15986== by 0x49BF46E: meta_stage_native_rebuild_views (meta-stage-native.c:142)
==15986== Address 0x1b076600 is 0 bytes inside a block of size 48 free'd
==15986== at 0x4839A0C: free (vg_replace_malloc.c:540)
==15986== by 0x49B59F3: meta_renderer_native_release_onscreen (meta-renderer-native.c:2651)
==15986== by 0x5211441: _cogl_onscreen_free (cogl-onscreen.c:167)
==15986== by 0x5210D81: _cogl_object_onscreen_indirect_free (cogl-onscreen.c:51)
==15986== by 0x51D0066: _cogl_object_default_unref (cogl-object.c:103)
==15986== by 0x520F989: _cogl_framebuffer_unref (cogl-framebuffer.c:1814)
==15986== by 0x51D00B1: cogl_object_unref (cogl-object.c:115)
==15986== by 0x536F3C7: clutter_stage_view_dispose (clutter-stage-view.c:304)
==15986== by 0x4B7DAF2: g_object_unref (gobject.c:3309)
==15986== by 0x4A9596C: g_list_foreach (glist.c:1013)
==15986== by 0x4A9599A: g_list_free_full (glist.c:223)
==15986== by 0x48D2737: meta_renderer_rebuild_views (meta-renderer.c:100)
==15986== Block was alloc'd at
==15986== at 0x483AB1A: calloc (vg_replace_malloc.c:762)
==15986== by 0x69A76B2: gbm_dri_surface_create (gbm_dri.c:1252)
==15986== by 0x69A6BFE: gbm_surface_create (gbm.c:600)
==15986== by 0x49B4E29: meta_renderer_native_create_surface_gbm (meta-renderer-native.c:2221)
==15986== by 0x49B57DB: meta_onscreen_native_allocate (meta-renderer-native.c:2569)
==15986== by 0x49B6423: meta_renderer_native_create_view (meta-renderer-native.c:3062)
==15986== by 0x48D26E7: meta_renderer_create_view (meta-renderer.c:78)
==15986== by 0x48D277A: meta_renderer_rebuild_views (meta-renderer.c:111)
==15986== by 0x49BF46E: meta_stage_native_rebuild_views (meta-stage-native.c:142)
==15986== by 0x49A75B5: meta_backend_native_update_screen_size (meta-backend-native.c:520)
==15986== by 0x48B01BB: meta_backend_sync_screen_size (meta-backend.c:224)
==15986== by 0x48B09B7: meta_backend_real_post_init (meta-backend.c:501)
https://gitlab.gnome.org/GNOME/mutter/merge_requests/622
Currently the EGLDevice code gets the display and calls eglInitialize.
As a follow-up it checks the required EGL extensions - technically it
could check the EGL device extensions earlier.
In either case, eglTerminate is missing. Thus the connection to the
display was still bound.
This was highlighted with Mesa commit d6edccee8da ("egl: add
EGL_platform_device support") + amdgpu.
In that case, since the eglTerminate is missing, we end up reusing the
underlying amdgpu_device due to some caching in libdrm_amdgpu. The
latter in itself being a good solution since it allows buffer sharing
across primary and render node of the same device.
Note: we should really get this in branches all the way back to 3.30.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/619
Fixes: 934184e23 ("MetaRendererNative: Add EGLDevice based rendering support")
Cc: Jonas Ådahl <jadahl@gmail.com>
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
Extract the next buffer -logic into a new function. This allows to
simplify copy_shared_framebuffer_cpu () making it more readable.
This change is a pure refactoring, no functional changes.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/593
There is no reason why we should have an internal type enum when we have
all the infrastructure to just use multiple GObject types. Also there
was no code sharing between the old "types", the only common API was
getting the framebuffer ID, so lets make that a vfunc.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/584