This adds HDCP state tracking through Client to HwcDisplay
When Client requests HDCP to be enabled for secure layers
Hdcpstate in the corresponding HwcDisplay is set up.
This is parsed to set the Content Protection and HDCP Content Type
properties for the connector in the next commit
Change-Id: I60dd4359ee2f87faba1df83c7faf286b34af43f6
Signed-off-by: Manasi Navare <navaremanasi@google.com>
This change adds a new CompositionAttributes struct which
tracks information about a given composition as it is
validated and subsequently presented.
Previously CompositionStats were tracked as totals for each
display. This change splits the stats according to the
CompositionAttributes for each presented composition.
This change only affects the reporting behavior of
CompositionStatsTracker. The stats logged by DumpState are
totaled so as to not be affected.
Change-Id: I050cce7f63891971cc807b9c5150d9b5d30f1f0b
The EdidWrapper lifecycle was previously managed by DrmConnector,
meaning the EDID parser was initialized when the connector was created.
This approach fails for physical connectors where a display is not
attached at boot, as no EDID blob is available to parse.
When a display was subsequently hot-plugged, the system would fall back
to a generic EdidWrapper. This provided incorrect or default display
properties to userspace, causing critical bugs such as:
* Incorrect DPI calculations, leading to improperly scaled UI in
Android.
* Inability to detect HDR capabilities or supported color modes.
This change moves the ownership and lifecycle management of the
EdidWrapper to HwcDisplay. By creating the parser only when a display is
actually connected, we ensure that the correct EDID is always parsed,
making hot-plug functionality work as intended.
Change-Id: I5e056e423bbac2b23a411395b4ce13ccd03c4b64
Signed-off-by: Gil Dekel <gildekel@google.com>
This change adds the buildflag HAS_LIBSYNC for managing
availability of libsync. This is necessary for the
unittests target for which libsync doesn't provide the
necessary variant.
DrmAtomicStateManager.cpp is the only file which depends
on libsync. Guards have been added using the HAS_LIBSYNC
flag, such that any method which would depend on libsync
is now stubbed when it is unavailable.
Change-Id: I101083074a9fad98e1c40c27b55f2eddf1c53581
Add perferto tracing around validate and present paths. Specifically
around code that blocks on the main thread (e.g. commit, fence waits).
These should increase the visibility of what is blocking the
presentation hot path in perfetto traces.
Change-Id: I6db60648c5e1d5f1a666ebc52f5ae5ad57e0e82a
Ensure that the next frame's list of used_planes is correct. The list of
used planes for the new frame is initialized to the previous frame's
list of planes when creating the AtomicRequest. If there is a
composition as a part of this request, the list should be cleared before
creating the new composition, since the list will be re-populated.
Neglecting to clear this left planes on the list when they shouldn't
have been, or the same plane multiple times. This led to some spurious
commit and validation failures on single display configurations, but on
multiple display configurations also resulted in highly visible stuttering.
Change-Id: Ie3fa1fc120fde13ee80f9a144c459526be2822cb
When DRM HWC starts, it resets all the connectors
and CRTCs to avoid the mimatch between drm hwc tracked
state and actual HW state programmed by the firmware
for the splash screen.
This fixes the MST connected boot issue.
Change-Id: I0773541b6bb227a2880d8442cc46411dc4c0127a
Signed-off-by: Manasi Navare <navaremanasi@google.com>
Currently, drm_hwcomposer has two main ways to lock up in the
composition hot path:
1. HwcDisplay::WaitForPresenttime(), where it looks at the expected
present time of the frame and sleeps until it is close to it (0.75
vsync period away from the target vsync).
2. DrmAtomicStateManager::WaitLastFrame(), where it waits on the
present fence of the last commit so that we don't call commit when
another present is pending
These are called in-order, which in certain multi-display configuration
with heterogenous refresh rates can lead to the slower display locking
up due to sleep in WaitForPresenttime().
This CL makes DrmAtomicStateManager::WaitLastFrame() public, and moves
its invocation to right before the call to
HwcDisplay::WaitForPresenttime(). This should minimize the impact of
WaitForPresenttime(), and allow drm_hwcomposer to hit more present
targets that it can hit.
Test: atest GraphicsComposerAidlCommandTest
Test: Manual testing w/ perfetto
Change-Id: Ic9c07ff0b6d00dfafce5dd109d8195886dd3094e
Signed-off-by: Su Hong Koo <sukoo@google.com>
The next frame's state needs to be initialized with the current frame's
state to ensure that it doesn't get reset incorrectly.
Change-Id: I00caab6ad4116dceba67cbd945b83c4d45277a39
This change modifies cursor behavior during atomic commit
so that the scaling factor is preserved. Previously, the
src rect was being overwritten to match the dimensions of
the dst rect, because it was assumed that scaling is not
permitted with the cursor plane. The new behavior will
preserve any existing scaling factor while resizing the
src rect. For hardware that cannot use scaling on the
cursor plane, this behavior should now be caught during
test commit, and trigger the appropriate fallback. For
hardware that can use scaling on the cursor plane, the
behavior is fixed such that the cursor will now appear
with the correct sizing.
Change-Id: I1d3e01441bdc5d7076b15d66b1a7a1a498ea64a9
This change refactors the IRect and FRect types into a single
templated type Rect<T>, which allows the implementation to be
shared across both variants. This change also adds convenience
getters for the rect widths and heights, and updates callsites
accordingly.
Change-Id: I38509631d57706266186a7b7fa21bd43c0860890
Make AtomicCommitArgs const in the different helper functions to build
the AtomicRequest. Additionally, reorder the parameters to reflect the
convention that input parameters are listed first, and out parameters
are listed after.
Change-Id: I0277ec4129fbcd6312e6df9ae3f15600e9755520
Add AtomicRequest struct to wrap the pending DrmModeAtomicReq and
related kms objects and state for the pending atomic commit.
After the AtomicRequest's property set has been committed, update the
internal DrmAtomicStateManager state to reflect what has been committed.
Change-Id: I49d39649eb957d69f724b53b91577a347a75527e
Rather than initializing the state associated with a new frame by
copying committed_frame_state_, check committed_frame_state_ directly
when needed.
Change-Id: I62043e15e70669ce6a8ac4635101d13d8efd7f15
In some cases, the position of the cursor is controlled by the src rect.
For example, this is done when the cursor extends beyond the top or left
edges of the screen. This is not compatible with the hw cursor plane
however, because scaling and panning are both disallowed. As a workaround,
the position of the dst rect needs to be adjusted in the opposite
direction (in some cases taking a negative-valued position,) which
will correctly position the cursor while also assigning an acceptible
value to the src rect.
Change-Id: Ide7f75e01481bcd602a33d222d1ae6862703a1cd
Making TestComposition const ensures that the Backend can't modify any
HwcDisplay state while creating and validating a composition.
Also make a bunch of other stuff const-correct since there is a const
version of GetPipe()
Change-Id: Ib7769d290148ce496b0165b64806dbd0a601b213
Backend shouldn't directly mutate HwcLayer state, so make HwcLayer
const. Make a few other related functions const correct as well.
Change-Id: Id7f8e255e9e72b756399b1a4dabc3db779d64bc9
A test commit or failed modesets, particularly when with modes of a
different resolution, would cause all subsequent pafe-flip commits to
fail.
The root cause was a premature state update within
SetDisplayModeIfNeeded. The `whole_display_rect_` member was being
modified during the commit preparation phase. This polluted the state
manager's internal view of the active display size, causing subsequent
frame compositions to be built with incorrect dimensions, which were
then rejected by the kernel on certain drivers that cannot handle
scaling on the fly.
This change fixes the issue by deferring the state update until after a
commit is successfully applied:
1. `whole_display_rect_` is now only updated inside `CommitFrame` after
a modesetting commit has been successfully applied to hardware.
2. `SetCompositionIfNeeded` is updated to use the dimensions from the
incoming `args.display_mode`, if available, when preparing a modeset.
Otherwise it will use the existing size in `whole_display_rect_`.
This ensures the plane is correctly configured for either the
requested mode, or the currently active one (for page-flips).
This prevents test-only operations from having side effects and ensures
the state manager's internal state remains consistent. It also prevents
state pollution on failed modesets.
Change-Id: Icf08b32c13879d394f883f34e6fed3d96a748a4f
Co-authored-by: Lucas Berthou <berlu@google.com>
Signed-off-by: Gil Dekel <gildekel@google.com>
Configuration groups for the Multiple Refresh Rate (MRR) feature support
is currently disabled in DRM HWComposer. This is because it is
insufficient to group modes solely based on their active region size.
The primary reasons for this insufficiency are:
1. drm-hwc clients may assume they can seamlessly switch between
configurations within the same group to support variable refresh
rates.
2. Not all System-on-a-Chip (SoC) architectures support seamless mode
transitions.
3. For SoCs that do support seamless switching, transitions often depend
on other hardware-specific properties like matching blanking periods.
4. A fallback to a non-seamless (blocking) modeset is unacceptable for
internal displays if a seamless transition fails, as this causes
flickering. The current framework does not handle such failures
gracefully.
To Resolve these challenges and re-enable seamless Multiple Refresh-Rate
transitions on internal panels, we add logic to validate all configs
against the preferred initial active config. This validation preforms a
seamless modeset test on each available config against the config that
was set during the display initialization. Configs that fail the
screening are assigned new group IDs.
Caveats:
1. Currently, this is only implemented for internal panels. External
display seamless transition between variable refresh rates is not
support. However this work can be extended to support seamless
transitions on external displays as well.
2. Grouping is only preformed for the preffered/active config at the
time of display init, and is valid only for the duration of the
current full modeset commit. No other groups are not created (since
they cannot be validated), and any new full commits will not honor
the guarantee provided by the check. This work can be extended to
refresh and validate all configs within the same group ID of any
incoming full modeset commit.
Change-Id: Ie2661e74bd3ff704b40c8c7ef50c56e604e5e8df
Signed-off-by: Gil Dekel <gildekel@google.com>
Error codes are never checked and working with errors as booleans
results in somewhat counter-intuitive logic.
Change CommitFrame() and ExecuteAtomicCommit() to return bools instead.
Change-Id: I5e8041fd4ddc99ef06184081a7f6def028bbe356
Signed-off-by: Gil Dekel <gildekel@google.com>
SurfaceFlinger should now be handling this race condition more robustly
and it is find to return BAD_DISPLAY in this case. Additionally, there
is no other thread which might be holding a resource resulting in a
deadlock or race during teardown.
Change-Id: I45740febccf2efae2fa470fdbdbe050daadb053b
This is a prerequisit to allow for multi-display commit at once.
It also removes the cognitive complexity of CommitFrame through addition
of helpers for all drm properties to be set.
Change-Id: Ifad7e574c9ea6ced09c677923868ce29656f33f3
Signed-off-by: Lucas Berthou <berlu@google.com>
This change removes a check in DrmPlane::IsValidForLayer which would
verify that the buffer size matches known accepted values from the
DRM_CAP_CURSOR or SIZE_HINTS properties. Those properties are required
to return valid buffer sizes for committing to the cursor plane, but
they are not meant to be exhaustive. As a result, this check was
returning false negatives, and forcing the cursor into client
composition unnecessarily. The intended usage is that these props
should be checked during buffer allocation, not during composition.
Instead, test commits are sufficient for detecting whether a buffer
is valid for the cursor plane, and triggering fallback logic as needed.
Change-Id: Iae14436a6f50e45a113a4d18de67e73810b2a83e
Signed-off-by: Andrew Wolfers <aswolfers@google.com>
Now that the helper thread doesn't acquire the global lock, we can wait
for the helper thread to exit without risk of deadlock.
Change-Id: Ibaf8a1a64fb1aa64f8b75fd9a8ae1eff81dae0df
Remove the usage of main_lock_ and ensure that mutex_ is held for no
larger a scope than is necessary.
Reorder some class members to keep protected members together.
Change-Id: Iaf29cf53e11d692fb3779b61b147abfcacf95746
The distinction between active/staged isn't important for state
tracking, so simplify management of these by using a std::queue.
Change-Id: I1871d3c2f5c6e6686baa9b6473bbbb7072077efc
Since the helper thread doesn't need to access KmsState, and we are only
using the most recently committed state, track the KmsState separately
from the KmsObjects.
The tracked KmsState doesn't need to be synchronized with the helper
thread.
Change-Id: Ic62e0753ee11d3870eb31892f18023688558ff9a
When preparing the properties for a commit, the state for the currently
active frame is used, rather than the last committed frame. This is
incorrect and could lead to a scenario such as:
- Frame N: commit enables plane 1
- Frame N+1: commit uses plane 1, 2, 3
- Frame N+2: if executed before staged_frame_state_ is moved to
active_frame_state_, the new KmsState::used_framebuffers will be
initialized to {1}
- commit uses planes 1, 2
- plane 3 is not disabled by the unused_planes code in CommitFrame
A similar problem exists for the KmsState::crtc_active_state.
To avoid this issue, always use the last committed state, regardless of
whether the previous frame has been presented or not.
Change-Id: I840b5b0ca3a3cf477882cacf6b1d5c0313ae80cf
Define DrmAtomicStateManager::KmsObjects struct to distinguish between
objects that are tracked for lifetime management and state that is
tracked for the purpose of preparing subsequent commits.
Change-Id: I5402959f17298102a904b83fbbf01577ae673e48
Shared state is protected by a combination of the local mutex_ and the
global lock. This change attempts to document and enforce that more
clearly using clang-tidy thread annotations.
Change unique_lock usage to lock_guard for cases that do not require
release of the mutex such as when using a condition variable.
Temporarily add a main_lock_ mutex which mirrors how
the global lock is being used for synchronization. Lock this at the
entry point to all public methods. This lock will be removed as a part
of subsequent refactoring and it used to more cleanly break up the
following changes in this series.
Some state is not properly protected by any lock, so temporarily disable
the warnings around access to that state until the synchronization is
resolved in subsequent changes.
Change-Id: I6f4f30c4e97f266146b0879c5255d6f2432f12a3
Ensure that the std::lock is declared early so that it can be referenced
by clang thread annotations.
Change-Id: I64e7290cc6ff6fcdebb119dc2ec7537387f4ae5c
This file already exists in android-base, so use this instead of
duplicating the macros in this project.
Since the copy in android-base provides a helper class to assist with
std::unique_lock, use that instead of disabling the warnings.
Change-Id: Ib1724045e3eea29946799fb99b3fbcfcc14a5013
Add DisplayHandle which is a typedef for int64_t. Use this type instead
of the HWC2 hwc2_display_t type.
Additionally, rename variable names to prefer `display_handle` over
`display_id`, since "DisplayId" is overloaded and carries a different
meaning in the Android framework.
Change-Id: I2a8ecce3b2c19fcd5e945d6c645f83d6a7d27a42
Wrap Android16 APIs in an if block to prevent breaking Android15
integration.
s/AidlHdcpLevels/drm::HdcpLevels
Add support for external HDR displays (dropped in previous cleanup).
clang-format-diff-19 nits
Change-Id: I897e0b42e0065a61ecfe28c280094b6c375d8a72
Signed-off-by: Sasha McIntosh <sashamcintosh@google.com>