1
0
Fork 0
mutter-performance-source/src/backends/native/meta-kms-impl-device-simple.c

1410 lines
46 KiB
C
Raw Normal View History

backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
/*
* Copyright (C) 2019-2020 Red Hat
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
*
* 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-kms-impl-device-simple.h"
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
#include "backends/native/meta-drm-buffer-gbm.h"
#include "backends/native/meta-kms-connector-private.h"
#include "backends/native/meta-kms-crtc-private.h"
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
#include "backends/native/meta-kms-device-private.h"
#include "backends/native/meta-kms-mode-private.h"
#include "backends/native/meta-kms-plane-private.h"
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
#include "backends/native/meta-kms-private.h"
#include "backends/native/meta-kms-update-private.h"
#include "backends/native/meta-kms-utils.h"
typedef struct _CachedModeSet
{
GList *connectors;
drmModeModeInfo *drm_mode;
} CachedModeSet;
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
struct _MetaKmsImplDeviceSimple
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
{
MetaKmsImplDevice parent;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
GSource *mode_set_fallback_feedback_source;
GList *mode_set_fallback_page_flip_datas;
GList *pending_page_flip_retries;
GSource *retry_page_flips_source;
GList *postponed_page_flip_datas;
GList *postponed_mode_set_fallback_datas;
GHashTable *cached_mode_sets;
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
};
static GInitableIface *initable_parent_iface;
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
static void
initable_iface_init (GInitableIface *iface);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceSimple, meta_kms_impl_device_simple,
META_TYPE_KMS_IMPL_DEVICE,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init))
static void
flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple);
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
static gboolean
set_connector_property (MetaKmsImplDevice *impl_device,
MetaKmsConnector *connector,
MetaKmsConnectorProp prop,
uint64_t value,
GError **error)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
uint32_t prop_id;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
int fd;
int ret;
prop_id = meta_kms_connector_get_prop_id (connector, prop);
if (!prop_id)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Property (%s) not found on connector %u",
meta_kms_connector_get_prop_name (connector, prop),
meta_kms_connector_get_id (connector));
return FALSE;
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
fd = meta_kms_impl_device_get_fd (impl_device);
ret = drmModeObjectSetProperty (fd,
meta_kms_connector_get_id (connector),
DRM_MODE_OBJECT_CONNECTOR,
prop_id,
value);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
if (ret != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
"Failed to set connector %u property %u: %s",
meta_kms_connector_get_id (connector),
prop_id,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
g_strerror (-ret));
return FALSE;
}
return TRUE;
}
static gboolean
process_connector_update (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
gpointer update_entry,
GError **error)
{
MetaKmsConnectorUpdate *connector_update = update_entry;
MetaKmsConnector *connector = connector_update->connector;
if (connector_update->dpms.has_update)
{
meta_topic (META_DEBUG_KMS,
"[simple] Setting DPMS on connector %u (%s) to %"
G_GUINT64_FORMAT,
meta_kms_connector_get_id (connector),
meta_kms_impl_device_get_path (impl_device),
connector_update->dpms.state);
if (!set_connector_property (impl_device,
connector,
META_KMS_CONNECTOR_PROP_DPMS,
connector_update->dpms.state,
error))
return FALSE;
}
if (connector_update->underscanning.has_update &&
connector_update->underscanning.is_active)
{
meta_topic (META_DEBUG_KMS,
"[simple] Setting underscanning on connector %u (%s) to "
"%" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT,
meta_kms_connector_get_id (connector),
meta_kms_impl_device_get_path (impl_device),
connector_update->underscanning.hborder,
connector_update->underscanning.vborder);
if (!set_connector_property (impl_device,
connector,
META_KMS_CONNECTOR_PROP_UNDERSCAN,
1,
error))
return FALSE;
if (!set_connector_property (impl_device,
connector,
META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER,
connector_update->underscanning.hborder,
error))
return FALSE;
if (!set_connector_property (impl_device,
connector,
META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER,
connector_update->underscanning.vborder,
error))
return FALSE;
}
else if (connector_update->underscanning.has_update)
{
meta_topic (META_DEBUG_KMS,
"[simple] Unsetting underscanning on connector %u (%s)",
meta_kms_connector_get_id (connector),
meta_kms_impl_device_get_path (impl_device));
if (!set_connector_property (impl_device,
connector,
META_KMS_CONNECTOR_PROP_UNDERSCAN,
0,
error))
return FALSE;
}
return TRUE;
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
static CachedModeSet *
cached_mode_set_new (GList *connectors,
const drmModeModeInfo *drm_mode)
{
CachedModeSet *cached_mode_set;
cached_mode_set = g_new0 (CachedModeSet, 1);
*cached_mode_set = (CachedModeSet) {
.connectors = g_list_copy (connectors),
.drm_mode = g_memdup (drm_mode, sizeof *drm_mode),
};
return cached_mode_set;
}
static void
cached_mode_set_free (CachedModeSet *cached_mode_set)
{
g_list_free (cached_mode_set->connectors);
g_free (cached_mode_set->drm_mode);
g_free (cached_mode_set);
}
static void
fill_connector_ids_array (GList *connectors,
uint32_t **out_connectors,
int *out_n_connectors)
{
GList *l;
int i;
*out_n_connectors = g_list_length (connectors);
*out_connectors = g_new0 (uint32_t, *out_n_connectors);
i = 0;
for (l = connectors; l; l = l->next)
{
MetaKmsConnector *connector = l->data;
(*out_connectors)[i++] = meta_kms_connector_get_id (connector);
}
}
static gboolean
set_plane_rotation (MetaKmsImplDevice *impl_device,
MetaKmsPlane *plane,
uint64_t rotation,
GError **error)
{
int fd;
uint32_t rotation_prop_id;
int ret;
fd = meta_kms_impl_device_get_fd (impl_device);
rotation_prop_id = meta_kms_plane_get_prop_id (plane,
META_KMS_PLANE_PROP_ROTATION);
meta_topic (META_DEBUG_KMS,
"[simple] Setting plane %u (%s) rotation to %" G_GUINT64_FORMAT,
meta_kms_plane_get_id (plane),
meta_kms_impl_device_get_path (impl_device),
rotation);
ret = drmModeObjectSetProperty (fd,
meta_kms_plane_get_id (plane),
DRM_MODE_OBJECT_PLANE,
rotation_prop_id,
rotation);
if (ret != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
"Failed to rotation property (%u) to %" G_GUINT64_FORMAT
" on plane %u: %s",
rotation_prop_id,
rotation,
meta_kms_plane_get_id (plane),
g_strerror (-ret));
return FALSE;
}
return TRUE;
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
static gboolean
process_mode_set (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
gpointer update_entry,
GError **error)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
MetaKmsImplDeviceSimple *impl_device_simple =
META_KMS_IMPL_DEVICE_SIMPLE (impl_device);
MetaKmsModeSet *mode_set = update_entry;
MetaKmsCrtc *crtc = mode_set->crtc;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
g_autofree uint32_t *connectors = NULL;
int n_connectors;
MetaKmsPlaneAssignment *plane_assignment;
drmModeModeInfo *drm_mode;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
uint32_t x, y;
uint32_t fb_id;
int fd;
int ret;
crtc = mode_set->crtc;
if (mode_set->mode)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
MetaDrmBuffer *buffer;
drm_mode = g_alloca (sizeof *drm_mode);
*drm_mode = *meta_kms_mode_get_drm_mode (mode_set->mode);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
fill_connector_ids_array (mode_set->connectors,
&connectors,
&n_connectors);
plane_assignment = meta_kms_update_get_primary_plane_assignment (update,
crtc);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
if (!plane_assignment)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Missing primary plane assignment for legacy mode set on CRTC %u",
meta_kms_crtc_get_id (crtc));
return FALSE;
}
x = meta_fixed_16_to_int (plane_assignment->src_rect.x);
y = meta_fixed_16_to_int (plane_assignment->src_rect.y);
if (plane_assignment->rotation)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
if (!set_plane_rotation (impl_device,
plane_assignment->plane,
plane_assignment->rotation,
error))
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
return FALSE;
}
buffer = plane_assignment->buffer;
fb_id = meta_drm_buffer_get_fb_id (buffer);
meta_topic (META_DEBUG_KMS,
"[simple] Setting mode of CRTC %u (%s) to %s",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device),
drm_mode->name);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
else
{
drm_mode = NULL;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
x = y = 0;
n_connectors = 0;
connectors = NULL;
fb_id = 0;
meta_topic (META_DEBUG_KMS,
"[simple] Unsetting mode of CRTC %u (%s)",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device));
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
fd = meta_kms_impl_device_get_fd (impl_device);
ret = drmModeSetCrtc (fd,
meta_kms_crtc_get_id (crtc),
fb_id,
x, y,
connectors, n_connectors,
drm_mode);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
if (ret != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
"Failed to set mode %s on CRTC %u: %s",
drm_mode ? drm_mode->name : "off",
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
meta_kms_crtc_get_id (crtc),
g_strerror (-ret));
return FALSE;
}
if (drm_mode)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
g_hash_table_replace (impl_device_simple->cached_mode_sets,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
crtc,
cached_mode_set_new (mode_set->connectors,
drm_mode));
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
else
{
g_hash_table_remove (impl_device_simple->cached_mode_sets, crtc);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
return TRUE;
}
static gboolean
process_crtc_gamma (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
gpointer update_entry,
GError **error)
{
MetaKmsCrtcGamma *gamma = update_entry;
MetaKmsCrtc *crtc = gamma->crtc;
int fd;
int ret;
meta_topic (META_DEBUG_KMS,
"[simple] Setting CRTC %u (%s) gamma, size: %d",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device),
gamma->size);
fd = meta_kms_impl_device_get_fd (impl_device);
ret = drmModeCrtcSetGamma (fd, meta_kms_crtc_get_id (crtc),
gamma->size,
gamma->red,
gamma->green,
gamma->blue);
if (ret != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
"drmModeCrtcSetGamma on CRTC %u failed: %s",
meta_kms_crtc_get_id (crtc),
g_strerror (-ret));
return FALSE;
}
return TRUE;
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
static gboolean
is_timestamp_earlier_than (uint64_t ts1,
uint64_t ts2)
{
if (ts1 == ts2)
return FALSE;
else
return ts2 - ts1 < UINT64_MAX / 2;
}
typedef struct _RetryPageFlipData
{
MetaKmsCrtc *crtc;
uint32_t fb_id;
MetaKmsPageFlipData *page_flip_data;
float refresh_rate;
uint64_t retry_time_us;
MetaKmsCustomPageFlipFunc custom_page_flip_func;
gpointer custom_page_flip_user_data;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
} RetryPageFlipData;
static void
retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data)
{
g_assert (!retry_page_flip_data->page_flip_data);
g_free (retry_page_flip_data);
}
static CachedModeSet *
get_cached_mode_set (MetaKmsImplDeviceSimple *impl_device_simple,
MetaKmsCrtc *crtc)
{
return g_hash_table_lookup (impl_device_simple->cached_mode_sets, crtc);
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
static float
get_cached_crtc_refresh_rate (MetaKmsImplDeviceSimple *impl_device_simple,
MetaKmsCrtc *crtc)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
CachedModeSet *cached_mode_set;
cached_mode_set = g_hash_table_lookup (impl_device_simple->cached_mode_sets,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
crtc);
g_assert (cached_mode_set);
return meta_calculate_drm_mode_refresh_rate (cached_mode_set->drm_mode);
}
#define meta_assert_in_kms_impl(kms) \
g_assert (meta_kms_in_impl_task (kms))
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
static gboolean
retry_page_flips (gpointer user_data)
{
MetaKmsImplDeviceSimple *impl_device_simple =
META_KMS_IMPL_DEVICE_SIMPLE (user_data);
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
uint64_t now_us;
GList *l;
now_us = g_source_get_time (impl_device_simple->retry_page_flips_source);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
l = impl_device_simple->pending_page_flip_retries;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
while (l)
{
RetryPageFlipData *retry_page_flip_data = l->data;
MetaKmsCrtc *crtc = retry_page_flip_data->crtc;
GList *l_next = l->next;
int fd;
int ret;
MetaKmsPageFlipData *page_flip_data;
MetaKmsCustomPageFlipFunc custom_page_flip_func;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
if (is_timestamp_earlier_than (now_us,
retry_page_flip_data->retry_time_us))
{
l = l_next;
continue;
}
custom_page_flip_func = retry_page_flip_data->custom_page_flip_func;
if (custom_page_flip_func)
{
meta_topic (META_DEBUG_KMS,
"[simple] Retrying custom page flip on CRTC %u (%s)",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device));
ret = custom_page_flip_func (retry_page_flip_data->custom_page_flip_user_data,
retry_page_flip_data->page_flip_data);
}
else
{
meta_topic (META_DEBUG_KMS,
"[simple] Retrying page flip on CRTC %u (%s) with %u",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device),
retry_page_flip_data->fb_id);
fd = meta_kms_impl_device_get_fd (impl_device);
ret = drmModePageFlip (fd,
meta_kms_crtc_get_id (crtc),
retry_page_flip_data->fb_id,
DRM_MODE_PAGE_FLIP_EVENT,
retry_page_flip_data->page_flip_data);
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
if (ret == -EBUSY)
{
float refresh_rate;
meta_topic (META_DEBUG_KMS,
"[simple] Rescheduling page flip retry on CRTC %u (%s)",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device));
refresh_rate =
get_cached_crtc_refresh_rate (impl_device_simple, crtc);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
retry_page_flip_data->retry_time_us +=
(uint64_t) (G_USEC_PER_SEC / refresh_rate);
l = l_next;
continue;
}
impl_device_simple->pending_page_flip_retries =
g_list_remove_link (impl_device_simple->pending_page_flip_retries, l);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
page_flip_data = g_steal_pointer (&retry_page_flip_data->page_flip_data);
if (ret != 0)
{
g_autoptr (GError) error = NULL;
g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (-ret),
"drmModePageFlip on CRTC %u failed: %s",
meta_kms_crtc_get_id (crtc),
g_strerror (-ret));
if (!g_error_matches (error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
g_critical ("Failed to page flip: %s", error->message);
meta_kms_page_flip_data_discard_in_impl (page_flip_data, error);
}
retry_page_flip_data_free (retry_page_flip_data);
l = l_next;
}
if (impl_device_simple->pending_page_flip_retries)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
GList *l;
uint64_t earliest_retry_time_us = 0;
for (l = impl_device_simple->pending_page_flip_retries; l; l = l->next)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
RetryPageFlipData *retry_page_flip_data = l->data;
if (l == impl_device_simple->pending_page_flip_retries ||
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
is_timestamp_earlier_than (retry_page_flip_data->retry_time_us,
earliest_retry_time_us))
earliest_retry_time_us = retry_page_flip_data->retry_time_us;
}
g_source_set_ready_time (impl_device_simple->retry_page_flips_source,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
earliest_retry_time_us);
return G_SOURCE_CONTINUE;
}
else
{
g_clear_pointer (&impl_device_simple->retry_page_flips_source,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
g_source_unref);
flush_postponed_page_flip_datas (impl_device_simple);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
return G_SOURCE_REMOVE;
}
}
static void
schedule_retry_page_flip (MetaKmsImplDeviceSimple *impl_device_simple,
MetaKmsCrtc *crtc,
uint32_t fb_id,
float refresh_rate,
MetaKmsPageFlipData *page_flip_data,
MetaKmsCustomPageFlipFunc custom_page_flip_func,
gpointer custom_page_flip_user_data)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
RetryPageFlipData *retry_page_flip_data;
uint64_t now_us;
uint64_t retry_time_us;
now_us = g_get_monotonic_time ();
retry_time_us = now_us + (uint64_t) (G_USEC_PER_SEC / refresh_rate);
retry_page_flip_data = g_new0 (RetryPageFlipData, 1);
*retry_page_flip_data = (RetryPageFlipData) {
.crtc = crtc,
.fb_id = fb_id,
.page_flip_data = meta_kms_page_flip_data_ref (page_flip_data),
.refresh_rate = refresh_rate,
.retry_time_us = retry_time_us,
.custom_page_flip_func = custom_page_flip_func,
.custom_page_flip_user_data = custom_page_flip_user_data,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
};
if (!impl_device_simple->retry_page_flips_source)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
MetaKmsImplDevice *impl_device =
META_KMS_IMPL_DEVICE (impl_device_simple);
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
MetaKms *kms = meta_kms_device_get_kms (device);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
GSource *source;
source = meta_kms_add_source_in_impl (kms, retry_page_flips,
impl_device_simple, NULL);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
g_source_set_ready_time (source, retry_time_us);
impl_device_simple->retry_page_flips_source = source;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
else
{
GList *l;
for (l = impl_device_simple->pending_page_flip_retries; l; l = l->next)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
RetryPageFlipData *pending_retry_page_flip_data = l->data;
uint64_t pending_retry_time_us =
pending_retry_page_flip_data->retry_time_us;
if (is_timestamp_earlier_than (retry_time_us, pending_retry_time_us))
{
g_source_set_ready_time (impl_device_simple->retry_page_flips_source,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
retry_time_us);
break;
}
}
}
impl_device_simple->pending_page_flip_retries =
g_list_append (impl_device_simple->pending_page_flip_retries,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
retry_page_flip_data);
}
static void
invoke_page_flip_datas (GList *page_flip_datas,
MetaPageFlipDataFeedbackFunc func)
{
g_list_foreach (page_flip_datas, (GFunc) func, NULL);
}
static void
clear_page_flip_datas (GList **page_flip_datas)
{
g_list_free_full (*page_flip_datas,
(GDestroyNotify) meta_kms_page_flip_data_unref);
*page_flip_datas = NULL;
}
static gboolean
mode_set_fallback_feedback_idle (gpointer user_data)
{
MetaKmsImplDeviceSimple *impl_device_simple = user_data;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
g_clear_pointer (&impl_device_simple->mode_set_fallback_feedback_source,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
g_source_unref);
if (impl_device_simple->pending_page_flip_retries)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
impl_device_simple->postponed_mode_set_fallback_datas =
g_steal_pointer (&impl_device_simple->mode_set_fallback_page_flip_datas);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
else
{
invoke_page_flip_datas (impl_device_simple->mode_set_fallback_page_flip_datas,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
meta_kms_page_flip_data_mode_set_fallback_in_impl);
clear_page_flip_datas (&impl_device_simple->mode_set_fallback_page_flip_datas);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
return G_SOURCE_REMOVE;
}
static gboolean
mode_set_fallback (MetaKmsImplDeviceSimple *impl_device_simple,
MetaKmsUpdate *update,
MetaKmsPlaneAssignment *plane_assignment,
MetaKmsPageFlipData *page_flip_data,
GError **error)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple);
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
MetaKms *kms = meta_kms_device_get_kms (device);
MetaKmsCrtc *crtc = meta_kms_page_flip_data_get_crtc (page_flip_data);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
CachedModeSet *cached_mode_set;
g_autofree uint32_t *connectors = NULL;
int n_connectors;
uint32_t fb_id;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
uint32_t x, y;
int fd;
int ret;
cached_mode_set = g_hash_table_lookup (impl_device_simple->cached_mode_sets,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
crtc);
if (!cached_mode_set)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Missing mode set for page flip fallback");
return FALSE;
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
fill_connector_ids_array (cached_mode_set->connectors,
&connectors,
&n_connectors);
fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
x = meta_fixed_16_to_int (plane_assignment->src_rect.x);
y = meta_fixed_16_to_int (plane_assignment->src_rect.y);
fd = meta_kms_impl_device_get_fd (impl_device);
ret = drmModeSetCrtc (fd,
meta_kms_crtc_get_id (crtc),
fb_id,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
x, y,
connectors, n_connectors,
cached_mode_set->drm_mode);
if (ret != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
"drmModeSetCrtc mode '%s' on CRTC %u failed: %s",
cached_mode_set->drm_mode->name,
meta_kms_crtc_get_id (crtc),
g_strerror (-ret));
return FALSE;
}
if (!impl_device_simple->mode_set_fallback_feedback_source)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
GSource *source;
source = meta_kms_add_source_in_impl (kms,
mode_set_fallback_feedback_idle,
impl_device_simple,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
NULL);
impl_device_simple->mode_set_fallback_feedback_source = source;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
impl_device_simple->mode_set_fallback_page_flip_datas =
g_list_prepend (impl_device_simple->mode_set_fallback_page_flip_datas,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
meta_kms_page_flip_data_ref (page_flip_data));
return TRUE;
}
static gboolean
dispatch_page_flip (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
MetaKmsPageFlipData *page_flip_data,
GError **error)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
MetaKmsImplDeviceSimple *impl_device_simple =
META_KMS_IMPL_DEVICE_SIMPLE (impl_device);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
MetaKmsCrtc *crtc;
MetaKmsPlaneAssignment *plane_assignment;
MetaKmsCustomPageFlipFunc custom_page_flip_func;
gpointer custom_page_flip_user_data;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
int fd;
int ret;
crtc = meta_kms_page_flip_data_get_crtc (page_flip_data);
plane_assignment = meta_kms_update_get_primary_plane_assignment (update,
crtc);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
fd = meta_kms_impl_device_get_fd (impl_device);
meta_kms_update_get_custom_page_flip_func (update,
&custom_page_flip_func,
&custom_page_flip_user_data);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
if (custom_page_flip_func)
{
meta_topic (META_DEBUG_KMS,
"[simple] Invoking custom page flip on CRTC %u (%s)",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device));
ret = custom_page_flip_func (custom_page_flip_user_data,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
meta_kms_page_flip_data_ref (page_flip_data));
}
else
{
uint32_t fb_id;
fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer);
meta_topic (META_DEBUG_KMS,
"[simple] Page flipping CRTC %u (%s) with %u, data: %p",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device),
fb_id,
page_flip_data);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
ret = drmModePageFlip (fd,
meta_kms_crtc_get_id (crtc),
fb_id,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
DRM_MODE_PAGE_FLIP_EVENT,
meta_kms_page_flip_data_ref (page_flip_data));
}
if (ret != 0)
meta_kms_page_flip_data_unref (page_flip_data);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
if (ret == -EBUSY)
{
CachedModeSet *cached_mode_set;
meta_topic (META_DEBUG_KMS,
"[simple] Scheduling page flip retry on CRTC %u (%s)",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device));
cached_mode_set = get_cached_mode_set (impl_device_simple, crtc);
if (cached_mode_set)
{
uint32_t fb_id;
drmModeModeInfo *drm_mode;
float refresh_rate;
if (plane_assignment)
fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer);
else
fb_id = 0;
drm_mode = cached_mode_set->drm_mode;
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
schedule_retry_page_flip (impl_device_simple,
crtc,
fb_id,
refresh_rate,
page_flip_data,
custom_page_flip_func,
custom_page_flip_user_data);
}
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Page flip of %u failed, and no mode set available",
meta_kms_crtc_get_id (crtc));
meta_kms_page_flip_data_unref (page_flip_data);
return FALSE;
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
else if (ret == -EINVAL)
{
meta_topic (META_DEBUG_KMS,
"[simple] Falling back to mode set on CRTC %u (%s)",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device));
if (!mode_set_fallback (impl_device_simple,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
update,
plane_assignment,
page_flip_data,
error))
{
meta_kms_page_flip_data_unref (page_flip_data);
return FALSE;
}
}
else if (ret != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
"drmModePageFlip on CRTC %u failed: %s",
meta_kms_crtc_get_id (crtc),
g_strerror (-ret));
meta_kms_page_flip_data_unref (page_flip_data);
return FALSE;
}
meta_kms_page_flip_data_unref (page_flip_data);
return TRUE;
}
static GList *
generate_page_flip_datas (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update)
{
GList *listeners;
GList *page_flip_datas = NULL;
listeners = g_list_copy (meta_kms_update_get_page_flip_listeners (update));
while (listeners)
{
MetaKmsPageFlipListener *listener = listeners->data;
MetaKmsCrtc *crtc = listener->crtc;
MetaKmsPageFlipData *page_flip_data;
GList *l;
page_flip_data = meta_kms_page_flip_data_new (impl_device, crtc);
page_flip_datas = g_list_append (page_flip_datas, page_flip_data);
meta_kms_page_flip_data_add_listener (page_flip_data,
listener->vtable,
listener->user_data);
listeners = g_list_delete_link (listeners, listeners);
l = listeners;
while (l)
{
MetaKmsPageFlipListener *other_listener = l->data;
GList *l_next = l->next;
if (other_listener->crtc == crtc)
{
meta_kms_page_flip_data_add_listener (page_flip_data,
other_listener->vtable,
other_listener->user_data);
listeners = g_list_delete_link (listeners, l);
}
l = l_next;
}
}
return page_flip_datas;
}
static gboolean
maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
GList **failed_planes,
GError **error)
{
g_autoptr (GList) page_flip_datas = NULL;
GList *l;
page_flip_datas = generate_page_flip_datas (impl_device, update);
for (l = page_flip_datas; l; l = l->next)
{
MetaKmsPageFlipData *page_flip_data = l->data;
if (!dispatch_page_flip (impl_device, update, page_flip_data, error))
{
if (!g_error_matches (*error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
{
MetaKmsCrtc *crtc =
meta_kms_page_flip_data_get_crtc (page_flip_data);
MetaKmsPlaneAssignment *plane_assignment;
MetaKmsPlaneFeedback *plane_feedback;
plane_assignment =
meta_kms_update_get_primary_plane_assignment (update, crtc);
plane_feedback =
meta_kms_plane_feedback_new_take_error (plane_assignment->plane,
plane_assignment->crtc,
g_error_copy (*error));
*failed_planes = g_list_prepend (*failed_planes, plane_feedback);
}
return FALSE;
}
}
return TRUE;
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
static gboolean
process_entries (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
GList *entries,
gboolean (* func) (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
gpointer entry_data,
GError **error),
GError **error)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
GList *l;
for (l = entries; l; l = l->next)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
if (!func (impl_device, update, l->data, error))
return FALSE;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
return TRUE;
}
static gboolean
process_cursor_plane_assignment (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
MetaKmsPlaneAssignment *plane_assignment,
GError **error)
{
uint32_t crtc_id;
int fd;
crtc_id = meta_kms_crtc_get_id (plane_assignment->crtc),
fd = meta_kms_impl_device_get_fd (impl_device);
if (!(plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED))
{
int width, height;
int ret = -1;
uint32_t handle_u32;
width = plane_assignment->dst_rect.width;
height = plane_assignment->dst_rect.height;
if (plane_assignment->buffer)
{
MetaDrmBufferGbm *buffer_gbm =
META_DRM_BUFFER_GBM (plane_assignment->buffer);
struct gbm_bo *bo;
union gbm_bo_handle handle;
bo = meta_drm_buffer_gbm_get_bo (buffer_gbm);
handle = gbm_bo_get_handle (bo);
handle_u32 = handle.u32;
}
else
{
handle_u32 = 0;
}
meta_topic (META_DEBUG_KMS,
"[simple] Setting HW cursor of CRTC %u (%s) to %u "
"(size: %dx%d, hot: (%d, %d))",
crtc_id,
meta_kms_impl_device_get_path (impl_device),
handle_u32,
width, height,
plane_assignment->cursor_hotspot.x,
plane_assignment->cursor_hotspot.y);
if (plane_assignment->cursor_hotspot.is_valid)
{
ret = drmModeSetCursor2 (fd,
crtc_id,
handle_u32,
width, height,
plane_assignment->cursor_hotspot.x,
plane_assignment->cursor_hotspot.y);
}
if (ret != 0)
{
ret = drmModeSetCursor (fd, crtc_id,
handle_u32,
width, height);
}
if (ret != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
"drmModeSetCursor failed: %s", g_strerror (-ret));
return FALSE;
}
}
meta_topic (META_DEBUG_KMS,
"[simple] Moving HW cursor of CRTC %u (%s) to (%d, %d)",
crtc_id,
meta_kms_impl_device_get_path (impl_device),
plane_assignment->dst_rect.x,
plane_assignment->dst_rect.y);
drmModeMoveCursor (fd,
crtc_id,
plane_assignment->dst_rect.x,
plane_assignment->dst_rect.y);
return TRUE;
}
static gboolean
process_plane_assignment (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
MetaKmsPlaneAssignment *plane_assignment,
MetaKmsPlaneFeedback **plane_feedback)
{
MetaKmsPlane *plane;
MetaKmsPlaneType plane_type;
GError *error = NULL;
plane = plane_assignment->plane;
plane_type = meta_kms_plane_get_plane_type (plane);
switch (plane_type)
{
case META_KMS_PLANE_TYPE_PRIMARY:
/* Handled as part of the mode-set and page flip. */
return TRUE;
case META_KMS_PLANE_TYPE_CURSOR:
if (!process_cursor_plane_assignment (impl_device, update,
plane_assignment,
&error))
{
*plane_feedback =
meta_kms_plane_feedback_new_take_error (plane,
plane_assignment->crtc,
g_steal_pointer (&error));
return FALSE;
}
else
{
return TRUE;
}
case META_KMS_PLANE_TYPE_OVERLAY:
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
"Overlay planes cannot be assigned");
*plane_feedback =
meta_kms_plane_feedback_new_take_error (plane,
plane_assignment->crtc,
g_steal_pointer (&error));
return TRUE;
}
g_assert_not_reached ();
}
static gboolean
process_plane_assignments (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
GList **failed_planes,
GError **error)
{
GList *l;
for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next)
{
MetaKmsPlaneAssignment *plane_assignment = l->data;
MetaKmsPlaneFeedback *plane_feedback;
if (!process_plane_assignment (impl_device, update, plane_assignment,
&plane_feedback))
{
if (g_error_matches (plane_feedback->error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
{
g_propagate_error (error,
g_steal_pointer (&plane_feedback->error));
meta_kms_plane_feedback_free (plane_feedback);
return FALSE;
}
*failed_planes = g_list_prepend (*failed_planes, plane_feedback);
if (plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL)
{
continue;
}
else
{
g_propagate_error (error, g_error_copy (plane_feedback->error));
return FALSE;
}
}
}
return TRUE;
}
static void
page_flip_handler (int fd,
unsigned int sequence,
unsigned int tv_sec,
unsigned int tv_usec,
void *user_data)
{
MetaKmsPageFlipData *page_flip_data = user_data;
MetaKmsImplDevice *impl_device;
MetaKmsCrtc *crtc;
meta_kms_page_flip_data_set_timings_in_impl (page_flip_data,
sequence, tv_sec, tv_usec);
impl_device = meta_kms_page_flip_data_get_impl_device (page_flip_data);
crtc = meta_kms_page_flip_data_get_crtc (page_flip_data);
meta_topic (META_DEBUG_KMS,
"[simple] Handling page flip callback from %s, data: %p, CRTC: %u",
meta_kms_impl_device_get_path (impl_device),
page_flip_data,
meta_kms_crtc_get_id (crtc));
meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data);
}
static void
meta_kms_impl_device_simple_setup_drm_event_context (MetaKmsImplDevice *impl,
drmEventContext *drm_event_context)
{
drm_event_context->version = 2;
drm_event_context->page_flip_handler = page_flip_handler;
}
static MetaKmsFeedback *
meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update)
{
GError *error = NULL;
GList *failed_planes = NULL;
meta_topic (META_DEBUG_KMS,
"[simple] Processing update %" G_GUINT64_FORMAT,
meta_kms_update_get_sequence_number (update));
if (!process_entries (impl_device,
update,
meta_kms_update_get_connector_updates (update),
process_connector_update,
&error))
goto err;
if (!process_entries (impl_device,
update,
meta_kms_update_get_mode_sets (update),
process_mode_set,
&error))
goto err;
if (!process_entries (impl_device,
update,
meta_kms_update_get_crtc_gammas (update),
process_crtc_gamma,
&error))
goto err;
if (!process_plane_assignments (impl_device, update, &failed_planes, &error))
goto err;
if (!maybe_dispatch_page_flips (impl_device, update, &failed_planes, &error))
goto err;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
return meta_kms_feedback_new_passed (failed_planes);
err:
return meta_kms_feedback_new_failed (failed_planes, error);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
static void
flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
invoke_page_flip_datas (impl_device_simple->postponed_page_flip_datas,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
meta_kms_page_flip_data_flipped_in_impl);
clear_page_flip_datas (&impl_device_simple->postponed_page_flip_datas);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
invoke_page_flip_datas (impl_device_simple->postponed_mode_set_fallback_datas,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
meta_kms_page_flip_data_mode_set_fallback_in_impl);
clear_page_flip_datas (&impl_device_simple->postponed_mode_set_fallback_datas);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
static void
meta_kms_impl_device_simple_handle_page_flip_callback (MetaKmsImplDevice *impl_device,
MetaKmsPageFlipData *page_flip_data)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
MetaKmsImplDeviceSimple *impl_device_simple =
META_KMS_IMPL_DEVICE_SIMPLE (impl_device);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
if (impl_device_simple->pending_page_flip_retries)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
impl_device_simple->postponed_page_flip_datas =
g_list_append (impl_device_simple->postponed_page_flip_datas,
meta_kms_page_flip_data_ref (page_flip_data));
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
else
{
meta_kms_page_flip_data_flipped_in_impl (page_flip_data);
}
meta_kms_page_flip_data_unref (page_flip_data);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
}
static void
meta_kms_impl_device_simple_discard_pending_page_flips (MetaKmsImplDevice *impl_device)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
MetaKmsImplDeviceSimple *impl_device_simple =
META_KMS_IMPL_DEVICE_SIMPLE (impl_device);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
GList *l;
if (!impl_device_simple->pending_page_flip_retries)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
return;
for (l = impl_device_simple->pending_page_flip_retries; l; l = l->next)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
RetryPageFlipData *retry_page_flip_data = l->data;
MetaKmsPageFlipData *page_flip_data;
page_flip_data = g_steal_pointer (&retry_page_flip_data->page_flip_data);
meta_topic (META_DEBUG_KMS,
"[simple] Discarding page flip retry for CRTC %u (%s)",
meta_kms_crtc_get_id (
meta_kms_page_flip_data_get_crtc (page_flip_data)),
meta_kms_impl_device_get_path (
meta_kms_page_flip_data_get_impl_device (page_flip_data)));
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL);
retry_page_flip_data_free (retry_page_flip_data);
}
g_clear_pointer (&impl_device_simple->pending_page_flip_retries, g_list_free);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
g_clear_pointer (&impl_device_simple->retry_page_flips_source,
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
g_source_destroy);
}
static void
meta_kms_impl_device_simple_finalize (GObject *object)
{
MetaKmsImplDeviceSimple *impl_device_simple =
META_KMS_IMPL_DEVICE_SIMPLE (object);
g_list_free_full (impl_device_simple->pending_page_flip_retries,
(GDestroyNotify) retry_page_flip_data_free);
g_list_free_full (impl_device_simple->postponed_page_flip_datas,
(GDestroyNotify) meta_kms_page_flip_data_unref);
g_list_free_full (impl_device_simple->postponed_mode_set_fallback_datas,
(GDestroyNotify) meta_kms_page_flip_data_unref);
g_clear_pointer (&impl_device_simple->mode_set_fallback_feedback_source,
g_source_destroy);
g_hash_table_destroy (impl_device_simple->cached_mode_sets);
G_OBJECT_CLASS (meta_kms_impl_device_simple_parent_class)->finalize (object);
}
static gboolean
meta_kms_impl_device_simple_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
MetaKmsImplDeviceSimple *impl_device_simple =
META_KMS_IMPL_DEVICE_SIMPLE (initable);
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple);
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
GList *l;
if (!initable_parent_iface->init (initable, cancellable, error))
return FALSE;
impl_device_simple->cached_mode_sets =
g_hash_table_new_full (NULL,
NULL,
NULL,
(GDestroyNotify) cached_mode_set_free);
for (l = meta_kms_device_get_crtcs (device); l; l = l->next)
{
MetaKmsCrtc *crtc = l->data;
MetaKmsPlane *plane;
plane = meta_kms_device_get_cursor_plane_for (device, crtc);
if (plane)
continue;
meta_topic (META_DEBUG_KMS,
"[simple] Adding fake cursor plane for CRTC %u (%s)",
meta_kms_crtc_get_id (crtc),
meta_kms_impl_device_get_path (impl_device));
meta_kms_device_add_fake_plane_in_impl (device,
META_KMS_PLANE_TYPE_CURSOR,
crtc);
}
return TRUE;
}
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
static void
meta_kms_impl_device_simple_init (MetaKmsImplDeviceSimple *impl_device_simple)
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
{
}
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
static void
initable_iface_init (GInitableIface *iface)
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
{
initable_parent_iface = g_type_interface_peek_parent (iface);
iface->init = meta_kms_impl_device_simple_initable_init;
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
}
static void
meta_kms_impl_device_simple_class_init (MetaKmsImplDeviceSimpleClass *klass)
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
{
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaKmsImplDeviceClass *impl_device_class =
META_KMS_IMPL_DEVICE_CLASS (klass);
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
object_class->finalize = meta_kms_impl_device_simple_finalize;
backend/native: Add and use transactional KMS API 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/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-04-04 20:36:41 +00:00
impl_device_class->setup_drm_event_context =
meta_kms_impl_device_simple_setup_drm_event_context;
impl_device_class->process_update =
meta_kms_impl_device_simple_process_update;
impl_device_class->handle_page_flip_callback =
meta_kms_impl_device_simple_handle_page_flip_callback;
impl_device_class->discard_pending_page_flips =
meta_kms_impl_device_simple_discard_pending_page_flips;
backends/native: Add basic KMS abstraction building blocks The intention with KMS abstraction is to hide away accessing the drm functions behind an API that allows us to have different kind of KMS implementations, including legacy non-atomic and atomic. The intention is also that the code interacting with the drm device should be able to be run in a different thread than the main thread. This means that we need to make sure that all drm*() API usage must only occur from within tasks that eventually can be run in the dedicated thread. The idea here is that MetaKms provides a outward facing API other places of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is an internal implementation that only gets interacted with via "tasks" posted via the MetaKms object. These tasks will in the future potentially be run on the dedicated KMS thread. Initially, we don't create any new threads. Likewise, MetaKmsDevice is a outward facing representation of a KMS device, while MetaKmsImplDevice is the corresponding implementation, which only runs from within the MetaKmsImpl tasks. This commit only moves opening and closing the device to this new API, while leaking the fd outside of the impl enclosure, effectively making the isolation for drm*() calls pointless. This, however, is necessary to allow gradual porting of drm interaction, and eventually the file descriptor in MetaGpuKms will be removed. For now, it's harmless, since everything still run in the main thread. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
2019-01-29 09:24:44 +00:00
}