Subject: [PATCH 10/21] wip: add tiled frame transaction seam

From: Justin Youens <[email-masked]>
Date: Sat, 15 Aug 2026 09:23:28 -0500

---
 src/backend/drm/TiledAtomic.cpp |  94 +++++++++
 src/backend/drm/TiledAtomic.hpp | 229 +++++++++++++++++++++
 tests/TiledAtomic.cpp           | 343 +++++++++++++++++++++++++++++++-
 3 files changed, 665 insertions(+), 1 deletion(-)

diff --git a/src/backend/drm/TiledAtomic.cpp b/src/backend/drm/TiledAtomic.cpp
index 1e6ead823ff2e5777cb153a66f8d3c4c2de70ce9..5c03a8ea4b458034cab8d50cc9ac3ececaefb1f7 100644
--- a/src/backend/drm/TiledAtomic.cpp
+++ b/src/backend/drm/TiledAtomic.cpp
@@ -117,6 +117,42 @@ namespace {
             addProperty(operations, request, member.primaryPlaneId, PLANE.crtcW, VIEWPORT.crtcW) &&
             addProperty(operations, request, member.primaryPlaneId, PLANE.crtcH, VIEWPORT.crtcH);
     }
+
+    void cleanupFrameRequest(const CSharedPointer<ITiledAtomicFrameOperations>& operations, drmModeAtomicReqPtr& request) noexcept {
+        if (request && operations)
+            operations->freeRequest(request);
+        request = nullptr;
+    }
+
+    struct SFrameBuildResources {
+        CSharedPointer<ITiledAtomicFrameOperations> operations;
+        drmModeAtomicReqPtr                         request = nullptr;
+
+        ~SFrameBuildResources() noexcept {
+            cleanupFrameRequest(operations, request);
+        }
+    };
+
+    [[nodiscard]] bool addFrameProperty(const CSharedPointer<ITiledAtomicFrameOperations>& operations, drmModeAtomicReqPtr request, uint32_t objectId, uint32_t propertyId,
+                                        uint64_t value) noexcept {
+        return operations->addProperty(request, objectId, propertyId, value) >= 0;
+    }
+
+    [[nodiscard]] bool addFrameMember(const CSharedPointer<ITiledAtomicFrameOperations>& operations, drmModeAtomicReqPtr request, const STiledAtomicMember& member,
+                                      uint32_t framebufferId) noexcept {
+        const auto& PLANE    = member.planeProperties;
+        const auto& VIEWPORT = member.viewport;
+        return addFrameProperty(operations, request, member.primaryPlaneId, PLANE.fbId, framebufferId) &&
+            addFrameProperty(operations, request, member.primaryPlaneId, PLANE.crtcId, member.crtcId) &&
+            addFrameProperty(operations, request, member.primaryPlaneId, PLANE.srcX, VIEWPORT.srcX) &&
+            addFrameProperty(operations, request, member.primaryPlaneId, PLANE.srcY, VIEWPORT.srcY) &&
+            addFrameProperty(operations, request, member.primaryPlaneId, PLANE.srcW, VIEWPORT.srcW) &&
+            addFrameProperty(operations, request, member.primaryPlaneId, PLANE.srcH, VIEWPORT.srcH) &&
+            addFrameProperty(operations, request, member.primaryPlaneId, PLANE.crtcX, static_cast<uint64_t>(static_cast<int64_t>(VIEWPORT.crtcX))) &&
+            addFrameProperty(operations, request, member.primaryPlaneId, PLANE.crtcY, static_cast<uint64_t>(static_cast<int64_t>(VIEWPORT.crtcY))) &&
+            addFrameProperty(operations, request, member.primaryPlaneId, PLANE.crtcW, VIEWPORT.crtcW) &&
+            addFrameProperty(operations, request, member.primaryPlaneId, PLANE.crtcH, VIEWPORT.crtcH);
+    }
 }
 
 namespace Aquamarine::NDRM::NTiledAtomic {
@@ -139,6 +175,13 @@ namespace Aquamarine::NDRM::NTiledAtomic {
             return prepared;
         }
     };
+
+    struct SFrameRequestAssembler {
+        static PPreparedTiledFrameRequest create(PResolvedTiledAtomicRoute route, CSharedPointer<ITiledAtomicFrameOperations> operations, drmModeAtomicReqPtr request) {
+            CSharedPointer<CPreparedTiledFrameRequest> prepared{new CPreparedTiledFrameRequest{std::move(route), std::move(operations), request}};
+            return prepared;
+        }
+    };
 }
 
 CResolvedTiledAtomicRoute::CResolvedTiledAtomicRoute(POutputBridgeObservation generationOwner, PScanGroupDefinition groupDefinition,
@@ -412,3 +455,54 @@ STiledAtomicBuildResult Aquamarine::NDRM::NTiledAtomic::buildTiledTestModeset(co
         return {.prepared = std::move(prepared), .error = eTiledAtomicError::NONE};
     } catch (...) { return {.error = eTiledAtomicError::ALLOCATION_FAILED}; }
 }
+
+CPreparedTiledFrameRequest::CPreparedTiledFrameRequest(PResolvedTiledAtomicRoute route, CSharedPointer<ITiledAtomicFrameOperations> operations,
+                                                       drmModeAtomicReqPtr request) noexcept : m_route(std::move(route)), m_operations(std::move(operations)), m_request(request) {}
+
+CPreparedTiledFrameRequest::~CPreparedTiledFrameRequest() noexcept {
+    cleanupFrameRequest(m_operations, m_request);
+}
+
+const PResolvedTiledAtomicRoute& CPreparedTiledFrameRequest::route() const noexcept {
+    return m_route;
+}
+
+drmModeAtomicReqPtr CPreparedTiledFrameRequest::request() const noexcept {
+    return m_request;
+}
+
+const CSharedPointer<ITiledAtomicFrameOperations>& CPreparedTiledFrameRequest::operations() const noexcept {
+    return m_operations;
+}
+
+STiledFrameRequestBuildResult::operator bool() const noexcept {
+    return error == eTiledAtomicError::NONE && prepared;
+}
+
+STiledFrameRequestBuildResult Aquamarine::NDRM::NTiledAtomic::buildTiledFrameRequest(const PResolvedTiledAtomicRoute&                   route,
+                                                                                     const CSharedPointer<ITiledAtomicFrameOperations>& operations) noexcept {
+    if (!route)
+        return {.error = eTiledAtomicError::INVALID_INPUT};
+    if (!operations)
+        return {.error = eTiledAtomicError::INVALID_OPERATIONS};
+
+    try {
+        SFrameBuildResources resources{.operations = operations, .request = operations->allocateRequest()};
+        if (!resources.request)
+            return {.error = eTiledAtomicError::REQUEST_ALLOCATION_FAILED};
+        for (const auto& MEMBER : route->members()) {
+            if (!addFrameMember(operations, resources.request, MEMBER, route->framebuffer().id))
+                return {.error = eTiledAtomicError::PROPERTY_ADD_FAILED};
+        }
+
+        auto prepared = SFrameRequestAssembler::create(route, operations, resources.request);
+        if (!prepared)
+            return {.error = eTiledAtomicError::ALLOCATION_FAILED};
+        resources.request = nullptr;
+        return {.prepared = std::move(prepared), .error = eTiledAtomicError::NONE};
+    } catch (...) { return {.error = eTiledAtomicError::ALLOCATION_FAILED}; }
+}
+
+STiledFrameTransactionResult::operator bool() const noexcept {
+    return status == eTiledFrameTransactionStatus::ACCEPTED;
+}
diff --git a/src/backend/drm/TiledAtomic.hpp b/src/backend/drm/TiledAtomic.hpp
index afe5914b367c67208fb3eb6a7e30e6bea69abf31..a113186cd2504be12cb8ece47b7536fe43e7efd1 100644
--- a/src/backend/drm/TiledAtomic.hpp
+++ b/src/backend/drm/TiledAtomic.hpp
@@ -1,9 +1,11 @@
 #pragma once
 
+#include "AtomicSubmit.hpp"
 #include "PlaneViewport.hpp"
 #include "TiledRuntime.hpp"
 
 #include <cstdint>
+#include <optional>
 #include <span>
 #include <vector>
 
@@ -154,6 +156,22 @@ namespace Aquamarine::NDRM::NTiledAtomic { // NOLINT(readability-identifier-nami
             };
         }
 
+        template <typename TOwner>
+        [[nodiscard]] bool matchesRuntimePlan(const STiledRuntimePlan<TOwner>& plan) const noexcept {
+            if (m_generation == 0 || m_generation != plan.generation || m_generationOwner.impl_ == nullptr || m_generationOwner.impl_ != plan.generationOwner.impl_ ||
+                m_definitionIdentity.impl_ == nullptr || m_definitionIdentity.impl_ != plan.definitionIdentity.impl_ || m_primaryCrtcId != plan.primaryCrtcId ||
+                m_crtcIds != plan.crtcIds || m_members.size() != plan.memberRoutes.size())
+                return false;
+
+            for (size_t index = 0; index < m_members.size(); ++index) {
+                const auto& MEMBER = m_members.at(index);
+                const auto& ROUTE  = plan.memberRoutes.at(index);
+                if (MEMBER.connectorId != ROUTE.connectorId || MEMBER.crtcId != ROUTE.crtcId || MEMBER.primaryPlaneId != ROUTE.primaryPlaneId)
+                    return false;
+            }
+            return true;
+        }
+
       private:
         CResolvedTiledAtomicRoute(POutputBridgeObservation generationOwner, PScanGroupDefinition groupDefinition, CSharedPointer<const CGroupDefinition> allocationDefinition,
                                   POutputDefinitionIdentity definitionIdentity, CSharedPointer<const CModeSet> modeSet, CSharedPointer<SOutputMode> outputMode,
@@ -238,6 +256,217 @@ namespace Aquamarine::NDRM::NTiledAtomic { // NOLINT(readability-identifier-nami
 
     [[nodiscard]] AQ_TILED_ATOMIC_PRIVATE STiledAtomicBuildResult buildTiledTestModeset(const PResolvedTiledAtomicRoute& route, int drmFD,
                                                                                         const CSharedPointer<ITiledAtomicRequestOperations>& operations) noexcept;
+
+    inline constexpr uint32_t                                     TILED_ATOMIC_FRAME_FLAGS = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT;
+
+    // A separate injected boundary keeps normal-frame submit capability out of
+    // the TEST_MODESET-only operations contract above. There is deliberately no
+    // production implementation or call site in this checkpoint.
+    class AQ_TILED_ATOMIC_PRIVATE ITiledAtomicFrameOperations {
+      public:
+        virtual ~ITiledAtomicFrameOperations() = default;
+
+        virtual drmModeAtomicReqPtr allocateRequest() noexcept                                                                                = 0;
+        virtual void                freeRequest(drmModeAtomicReqPtr request) noexcept                                                         = 0;
+        virtual int                 addProperty(drmModeAtomicReqPtr request, uint32_t objectId, uint32_t propertyId, uint64_t value) noexcept = 0;
+        virtual int                 submit(int drmFD, drmModeAtomicReqPtr request, uint32_t flags, void* userData) noexcept                   = 0;
+    };
+
+    enum class eTiledFrameTransactionStatus : uint8_t {
+        ACCEPTED = 0,
+        ACCEPTED_INVARIANT_FAILURE,
+        INVALID_INPUT,
+        ROUTE_RUNTIME_MISMATCH,
+        INVALID_OPERATIONS,
+        REQUEST_ALLOCATION_FAILED,
+        PROPERTY_ADD_FAILED,
+        RUNTIME_PREPARE_FAILED,
+        RESERVATION_FAILED,
+        RESERVATION_BIND_FAILED,
+        SUBMISSION_FAILED,
+        ALLOCATION_FAILED,
+    };
+
+    class CPreparedTiledFrameRequest;
+    using PPreparedTiledFrameRequest = CSharedPointer<const CPreparedTiledFrameRequest>;
+
+    class AQ_TILED_ATOMIC_PRIVATE CPreparedTiledFrameRequest final {
+      public:
+        CPreparedTiledFrameRequest(const CPreparedTiledFrameRequest&)            = delete;
+        CPreparedTiledFrameRequest(CPreparedTiledFrameRequest&&)                 = delete;
+        CPreparedTiledFrameRequest& operator=(const CPreparedTiledFrameRequest&) = delete;
+        CPreparedTiledFrameRequest& operator=(CPreparedTiledFrameRequest&&)      = delete;
+        ~CPreparedTiledFrameRequest() noexcept;
+
+        [[nodiscard]] const PResolvedTiledAtomicRoute&                   route() const noexcept;
+        [[nodiscard]] drmModeAtomicReqPtr                                request() const noexcept;
+        [[nodiscard]] const CSharedPointer<ITiledAtomicFrameOperations>& operations() const noexcept;
+
+      private:
+        CPreparedTiledFrameRequest(PResolvedTiledAtomicRoute route, CSharedPointer<ITiledAtomicFrameOperations> operations, drmModeAtomicReqPtr request) noexcept;
+
+        PResolvedTiledAtomicRoute                   m_route;
+        CSharedPointer<ITiledAtomicFrameOperations> m_operations;
+        drmModeAtomicReqPtr                         m_request = nullptr;
+
+        friend struct SFrameRequestAssembler;
+    };
+
+    struct AQ_TILED_ATOMIC_PRIVATE STiledFrameRequestBuildResult {
+        PPreparedTiledFrameRequest prepared;
+        eTiledAtomicError          error = eTiledAtomicError::INVALID_INPUT;
+
+        explicit                   operator bool() const noexcept;
+    };
+
+    // Emits only the frozen primary-plane FB/CRTC assignment and viewport.
+    // It never adds connector, CRTC, MODE_ID, ACTIVE, or mode-blob state.
+    [[nodiscard]] AQ_TILED_ATOMIC_PRIVATE STiledFrameRequestBuildResult buildTiledFrameRequest(const PResolvedTiledAtomicRoute&                   route,
+                                                                                               const CSharedPointer<ITiledAtomicFrameOperations>& operations) noexcept;
+
+    struct AQ_TILED_ATOMIC_PRIVATE STiledFrameTransactionEffects {
+        bool                                 requestBuilt        = false;
+        bool                                 runtimePrepared     = false;
+        bool                                 reservationReserved = false;
+        bool                                 reservationBound    = false;
+        bool                                 submitInvoked       = false;
+        bool                                 kmsAccepted         = false;
+        bool                                 runtimeAccepted     = false;
+        bool                                 registryAccepted    = false;
+        bool                                 runtimeRolledBack   = false;
+        bool                                 registryRolledBack  = false;
+        STiledRuntimeAcceptEffects           runtimeAccept;
+        std::optional<STiledFlipReservation> reservation;
+    };
+
+    struct AQ_TILED_ATOMIC_PRIVATE STiledFrameTransactionResult {
+        eTiledFrameTransactionStatus       status              = eTiledFrameTransactionStatus::INVALID_INPUT;
+        eTiledRuntimePrepareError          runtimePrepareError = eTiledRuntimePrepareError::NONE;
+        eTiledReservationError             reservationError    = eTiledReservationError::NONE;
+        std::optional<SAtomicSubmitResult> submission;
+        STiledFrameTransactionEffects      effects;
+
+        explicit                           operator bool() const noexcept;
+    };
+
+    // transactionId must come from the backend-wide nonzero, never-reused
+    // allocator documented by STiledFlipRoute. This seam additionally relies
+    // on same-event-thread, non-reentrant submit operations. A successful KMS
+    // call is linearized as runtime.accept() followed by registry.accept(); an
+    // impossible failure in either leaves the accepted/prepared ownership and
+    // reservation intact for a later quiesce/recovery path.
+    template <typename TOwner>
+    [[nodiscard]] STiledFrameTransactionResult submitTiledFrameTransaction(const PResolvedTiledAtomicRoute& route, CTiledFrameRuntime<TOwner>& runtime,
+                                                                           CTiledFlipReservationRegistry& registry, STiledRuntimeFrame<TOwner> frame, uintptr_t transactionId,
+                                                                           uint64_t deadlineNs, int drmFD, const CSharedPointer<ITiledAtomicFrameOperations>& operations) noexcept {
+        STiledFrameTransactionResult result;
+        if (!route || !operations || drmFD < 0 || transactionId == 0 || deadlineNs == 0 || frame.framebufferId != route->framebuffer().id) {
+            result.status = !operations || drmFD < 0 ? eTiledFrameTransactionStatus::INVALID_OPERATIONS : eTiledFrameTransactionStatus::INVALID_INPUT;
+            return result;
+        }
+        if (!route->matchesRuntimePlan(runtime.activePlan())) {
+            result.status = eTiledFrameTransactionStatus::ROUTE_RUNTIME_MISMATCH;
+            return result;
+        }
+        if (runtime.state() != eTiledRuntimeState::PUBLISHED_IDLE) {
+            result.runtimePrepareError = eTiledRuntimePrepareError::INVALID_STATE;
+            result.status              = eTiledFrameTransactionStatus::RUNTIME_PREPARE_FAILED;
+            return result;
+        }
+
+        const auto BUILT = buildTiledFrameRequest(route, operations);
+        if (!BUILT) {
+            switch (BUILT.error) {
+                case eTiledAtomicError::INVALID_INPUT: result.status = eTiledFrameTransactionStatus::INVALID_INPUT; break;
+                case eTiledAtomicError::INVALID_OPERATIONS: result.status = eTiledFrameTransactionStatus::INVALID_OPERATIONS; break;
+                case eTiledAtomicError::REQUEST_ALLOCATION_FAILED: result.status = eTiledFrameTransactionStatus::REQUEST_ALLOCATION_FAILED; break;
+                case eTiledAtomicError::PROPERTY_ADD_FAILED: result.status = eTiledFrameTransactionStatus::PROPERTY_ADD_FAILED; break;
+                default: result.status = eTiledFrameTransactionStatus::ALLOCATION_FAILED; break;
+            }
+            return result;
+        }
+        result.effects.requestBuilt = true;
+
+        const auto ROLLBACK_RUNTIME = [&]() noexcept {
+            if (result.effects.runtimePrepared)
+                result.effects.runtimeRolledBack = runtime.rollbackPrepared();
+        };
+        const auto ROLLBACK_REGISTRY = [&]() noexcept {
+            if (result.effects.reservationReserved && result.effects.reservation)
+                result.effects.registryRolledBack = registry.rollback(*result.effects.reservation);
+        };
+
+        try {
+            STiledFlipRoute runtimeRoute{
+                .transactionId = transactionId,
+                .generation    = route->generation(),
+                .crtcIds       = {route->crtcIds().begin(), route->crtcIds().end()},
+            };
+            result.runtimePrepareError = runtime.prepare(std::move(runtimeRoute), std::move(frame), deadlineNs);
+            if (result.runtimePrepareError != eTiledRuntimePrepareError::NONE) {
+                result.status = eTiledFrameTransactionStatus::RUNTIME_PREPARE_FAILED;
+                return result;
+            }
+            result.effects.runtimePrepared = true;
+
+            const auto* PREPARED_ROUTE = runtime.preparedRoute();
+            if (!PREPARED_ROUTE) {
+                ROLLBACK_RUNTIME();
+                result.status = eTiledFrameTransactionStatus::RUNTIME_PREPARE_FAILED;
+                return result;
+            }
+
+            const auto RESERVED     = registry.reserveAll(*PREPARED_ROUTE);
+            result.reservationError = RESERVED.error;
+            if (!RESERVED) {
+                ROLLBACK_RUNTIME();
+                result.status = eTiledFrameTransactionStatus::RESERVATION_FAILED;
+                return result;
+            }
+            result.effects.reservationReserved = true;
+            result.effects.reservation         = RESERVED.reservation;
+
+            if (!runtime.bindReservation(RESERVED.reservation)) {
+                ROLLBACK_RUNTIME();
+                ROLLBACK_REGISTRY();
+                result.status = eTiledFrameTransactionStatus::RESERVATION_BIND_FAILED;
+                return result;
+            }
+            result.effects.reservationBound = true;
+
+            result.effects.submitInvoked = true;
+            const auto SUBMISSION        = submitAtomicRequest(
+                drmFD, BUILT.prepared->request(), TILED_ATOMIC_FRAME_FLAGS, transactionId,
+                [&preparedOperations = BUILT.prepared->operations()](int fd, drmModeAtomicReqPtr request, uint32_t flags, void* userData) noexcept {
+                    return preparedOperations->submit(fd, request, flags, userData);
+                },
+                [&result, &runtime, &registry, &reserved = RESERVED.reservation](int returnCode) noexcept {
+                    if (returnCode != 0)
+                        return;
+                    result.effects.kmsAccepted     = true;
+                    result.effects.runtimeAccept   = runtime.accept();
+                    result.effects.runtimeAccepted = result.effects.runtimeAccept.accepted;
+                    if (result.effects.runtimeAccepted)
+                        result.effects.registryAccepted = registry.accept(reserved);
+                });
+            result.submission = SUBMISSION;
+
+            if (!SUBMISSION) {
+                ROLLBACK_RUNTIME();
+                ROLLBACK_REGISTRY();
+                result.status = eTiledFrameTransactionStatus::SUBMISSION_FAILED;
+                return result;
+            }
+            result.status = result.effects.runtimeAccepted && result.effects.registryAccepted ? eTiledFrameTransactionStatus::ACCEPTED :
+                                                                                                eTiledFrameTransactionStatus::ACCEPTED_INVARIANT_FAILURE;
+            return result;
+        } catch (...) {
+            ROLLBACK_RUNTIME();
+            ROLLBACK_REGISTRY();
+            result.status = eTiledFrameTransactionStatus::ALLOCATION_FAILED;
+            return result;
+        }
+    }
 }
 
 #undef AQ_TILED_ATOMIC_PRIVATE
diff --git a/tests/TiledAtomic.cpp b/tests/TiledAtomic.cpp
index adfffda3f060990c0d34535ebc8690ef8e001668..933c32ac548f2655f753d5c9d3eee384651dcf6e 100644
--- a/tests/TiledAtomic.cpp
+++ b/tests/TiledAtomic.cpp
@@ -1,8 +1,10 @@
 #include "backend/drm/TiledAtomic.hpp"
 
 #include <algorithm>
+#include <cerrno>
 #include <cstdint>
 #include <iostream>
+#include <memory>
 #include <ranges>
 #include <string_view>
 #include <thread>
@@ -320,6 +322,127 @@ namespace {
     }
 
     struct SForeignIdentityCarrier {};
+
+    struct SFrameOwner {
+        uint64_t id = 0;
+    };
+
+    using PFrameOwner   = std::shared_ptr<SFrameOwner>;
+    using SFrameRuntime = CTiledFrameRuntime<PFrameOwner>;
+
+    PFrameOwner frameOwner(uint64_t id) {
+        return std::make_shared<SFrameOwner>(SFrameOwner{.id = id});
+    }
+
+    SFrameRuntime::SFrame runtimeFrame(uint64_t framebufferId, uint64_t bufferId, PFrameOwner framebufferOwner, PFrameOwner bufferOwner) {
+        return {
+            .framebufferId    = framebufferId,
+            .bufferId         = bufferId,
+            .framebufferOwner = std::move(framebufferOwner),
+            .bufferOwner      = std::move(bufferOwner),
+        };
+    }
+
+    std::vector<SFrameRuntime::SMemberFrame> currentFrames(const PResolvedTiledAtomicRoute& route, uint64_t firstFramebufferId, uint64_t bufferId, const PFrameOwner& bufferOwner) {
+        std::vector<SFrameRuntime::SMemberFrame> frames;
+        frames.reserve(route->crtcIds().size());
+        size_t index = 0;
+        for (const auto CRTC_ID : route->crtcIds()) {
+            frames.push_back({
+                .crtcId = CRTC_ID,
+                .frame  = runtimeFrame(firstFramebufferId + index, bufferId, frameOwner(firstFramebufferId + index), bufferOwner),
+            });
+            ++index;
+        }
+        return frames;
+    }
+
+    struct SFrameRecorder final : ITiledAtomicFrameOperations {
+        drmModeAtomicReqPtr allocateRequest() noexcept override {
+            ++allocations;
+            // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): opaque fake request identity for the injected test boundary
+            return reinterpret_cast<drmModeAtomicReqPtr>(this);
+        }
+
+        void freeRequest(drmModeAtomicReqPtr request) noexcept override {
+            // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): matches allocateRequest's fake identity
+            if (request == reinterpret_cast<drmModeAtomicReqPtr>(this))
+                ++frees;
+        }
+
+        int addProperty(drmModeAtomicReqPtr, uint32_t objectId, uint32_t propertyId, uint64_t value) noexcept override {
+            try {
+                properties.push_back({.objectId = objectId, .propertyId = propertyId, .value = value});
+                return static_cast<int>(properties.size() - 1);
+            } catch (...) { return -1; }
+        }
+
+        int submit(int fd, drmModeAtomicReqPtr request, uint32_t flags, void* userData) noexcept override {
+            ++submits;
+            submittedFD      = fd;
+            submittedRequest = request;
+            submittedFlags   = flags;
+            // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,performance-no-int-to-ptr): inspect the injected opaque event token
+            submittedToken = reinterpret_cast<uintptr_t>(userData);
+            if (runtime)
+                runtimeStateDuringSubmit = runtime->state();
+            if (registry) {
+                transactionCountDuringSubmit = registry->transactionCount();
+                routeDuringSubmit            = registry->routeEvent(submittedToken, observedCrtcId);
+            }
+            return submitResult;
+        }
+
+        SFrameRuntime*                 runtime                      = nullptr;
+        CTiledFlipReservationRegistry* registry                     = nullptr;
+        uint32_t                       observedCrtcId               = 0;
+        int                            submitResult                 = 0;
+        size_t                         allocations                  = 0;
+        size_t                         frees                        = 0;
+        size_t                         submits                      = 0;
+        int                            submittedFD                  = -1;
+        drmModeAtomicReqPtr            submittedRequest             = nullptr;
+        uint32_t                       submittedFlags               = 0;
+        uintptr_t                      submittedToken               = 0;
+        eTiledRuntimeState             runtimeStateDuringSubmit     = eTiledRuntimeState::STAGED;
+        eTiledRouteEventResult         routeDuringSubmit            = eTiledRouteEventResult::NOT_OWNED;
+        size_t                         transactionCountDuringSubmit = 0;
+        std::vector<SPropertyWrite>    properties;
+    };
+
+    void appendFrameExpected(std::vector<SPropertyWrite>& expected, const STiledAtomicMember& member, uint32_t framebufferId) {
+        const auto& PLANE    = member.planeProperties;
+        const auto& VIEWPORT = member.viewport;
+        const auto  append   = [&](uint32_t propertyId, uint64_t value) { expected.push_back({.objectId = member.primaryPlaneId, .propertyId = propertyId, .value = value}); };
+        append(PLANE.fbId, framebufferId);
+        append(PLANE.crtcId, member.crtcId);
+        append(PLANE.srcX, VIEWPORT.srcX);
+        append(PLANE.srcY, VIEWPORT.srcY);
+        append(PLANE.srcW, VIEWPORT.srcW);
+        append(PLANE.srcH, VIEWPORT.srcH);
+        append(PLANE.crtcX, static_cast<uint64_t>(static_cast<int64_t>(VIEWPORT.crtcX)));
+        append(PLANE.crtcY, static_cast<uint64_t>(static_cast<int64_t>(VIEWPORT.crtcY)));
+        append(PLANE.crtcW, VIEWPORT.crtcW);
+        append(PLANE.crtcH, VIEWPORT.crtcH);
+    }
+
+    bool teardown(SFrameRuntime& runtime, CTiledFlipReservationRegistry& registry) {
+        if (runtime.state() != eTiledRuntimeState::QUIESCED && runtime.state() != eTiledRuntimeState::TEARDOWN) {
+            const auto effects = runtime.quiesce(eTiledQuiesceReason::BACKEND_TEARDOWN);
+            if (!effects.requestRecovery)
+                return false;
+            if (effects.rollbackReservation && effects.reservation && !registry.rollback(*effects.reservation))
+                return false;
+            if (effects.quiesceReservation && effects.reservation && !registry.quiesce(*effects.reservation))
+                return false;
+        }
+        if (runtime.state() != eTiledRuntimeState::TEARDOWN) {
+            const auto retired = runtime.retire(eTiledRetirementProof::BACKEND_TEARDOWN_NO_CALLBACKS);
+            if (!retired.retired)
+                return false;
+        }
+        return registry.shutdown(eTiledRegistryShutdownProof::BACKEND_NO_CALLBACKS) && runtime.readyForDestruction() && registry.readyForDestruction();
+    }
 }
 
 int main() {
@@ -399,7 +522,7 @@ int main() {
         CHECK(!sameOwner(MEMBER.primaryPlane, MEMBER.crtc->primary));
     }
 
-    const auto runtimePlan = resolved.route->runtimePlan<CSharedPointer<CDRMFB>>();
+    const auto runtimePlan = resolved.route->runtimePlan<PFrameOwner>();
     CHECK(runtimePlan.generation == resolved.route->generation());
     CHECK(sameOwner(runtimePlan.generationOwner, installed));
     CHECK(sameOwner(runtimePlan.definitionIdentity, GROUP.definitionIdentity()));
@@ -459,5 +582,223 @@ int main() {
     CHECK(duplicateRecorder->frees == 1);
     CHECK(duplicateRecorder->destroyedBlobs == std::vector<uint32_t>({900}));
 
+    static_assert(noexcept(submitTiledFrameTransaction(std::declval<const PResolvedTiledAtomicRoute&>(), std::declval<SFrameRuntime&>(),
+                                                       std::declval<CTiledFlipReservationRegistry&>(), std::declval<SFrameRuntime::SFrame>(), uintptr_t{1}, uint64_t{1}, 1,
+                                                       std::declval<const CSharedPointer<ITiledAtomicFrameOperations>&>())));
+
+    // 1. Successful submission is observed only after preparation and an
+    // all-member RESERVED route; accepted ownership stays in the runtime.
+    {
+        SFrameRuntime runtime(resolved.route->runtimePlan<PFrameOwner>());
+        const auto    oldBuffer = frameOwner(100);
+        CHECK(runtime.publishIdle(currentFrames(resolved.route, 700, 500, oldBuffer)));
+        CTiledFlipReservationRegistry registry;
+        auto                          frameRecorder                 = makeShared<SFrameRecorder>();
+        frameRecorder->runtime                                      = &runtime;
+        frameRecorder->registry                                     = &registry;
+        frameRecorder->observedCrtcId                               = resolved.route->crtcIds().front();
+        CSharedPointer<ITiledAtomicFrameOperations> frameOperations = frameRecorder;
+
+        auto                                        newFramebuffer     = frameOwner(200);
+        auto                                        newBuffer          = frameOwner(201);
+        const std::weak_ptr<SFrameOwner>            newFramebufferWeak = newFramebuffer;
+        const std::weak_ptr<SFrameOwner>            newBufferWeak      = newBuffer;
+        auto                                        newFrame           = runtimeFrame(resolved.route->framebuffer().id, 600, std::move(newFramebuffer), std::move(newBuffer));
+
+        const auto transaction = submitTiledFrameTransaction(resolved.route, runtime, registry, std::move(newFrame), 1'001, 50'000, 19, frameOperations);
+        CHECK(static_cast<bool>(transaction));
+        CHECK(transaction.status == eTiledFrameTransactionStatus::ACCEPTED);
+        CHECK(transaction.submission.has_value());
+        CHECK(transaction.submission.value_or(SAtomicSubmitResult{}).returnCode == 0);
+        CHECK(transaction.submission.value_or(SAtomicSubmitResult{}).error == 0);
+        CHECK(transaction.effects.requestBuilt);
+        CHECK(transaction.effects.runtimePrepared);
+        CHECK(transaction.effects.reservationReserved);
+        CHECK(transaction.effects.reservationBound);
+        CHECK(transaction.effects.submitInvoked);
+        CHECK(transaction.effects.kmsAccepted);
+        CHECK(transaction.effects.runtimeAccepted);
+        CHECK(transaction.effects.registryAccepted);
+        CHECK(!transaction.effects.runtimeRolledBack);
+        CHECK(!transaction.effects.registryRolledBack);
+        CHECK(transaction.effects.runtimeAccept.accepted);
+        CHECK(transaction.effects.runtimeAccept.schedulerSubmit);
+        CHECK(transaction.effects.reservation.has_value());
+        CHECK(runtime.state() == eTiledRuntimeState::PUBLISHED_IN_FLIGHT);
+        CHECK(registry.state(transaction.effects.reservation.value_or(STiledFlipReservation{})) == eTiledReservationState::IN_FLIGHT);
+        CHECK(registry.routeEvent(1'001, resolved.route->crtcIds().front()) == eTiledRouteEventResult::ROUTABLE);
+        CHECK(frameRecorder->runtimeStateDuringSubmit == eTiledRuntimeState::PUBLISHED_IDLE);
+        CHECK(frameRecorder->routeDuringSubmit == eTiledRouteEventResult::RESERVED);
+        CHECK(frameRecorder->transactionCountDuringSubmit == 1);
+        CHECK(frameRecorder->submittedFD == 19);
+        CHECK(frameRecorder->submittedRequest != nullptr);
+        CHECK(frameRecorder->submittedFlags == TILED_ATOMIC_FRAME_FLAGS);
+        CHECK(frameRecorder->submittedToken == 1'001);
+        CHECK(frameRecorder->submits == 1);
+        CHECK(frameRecorder->allocations == 1);
+        CHECK(frameRecorder->frees == 1);
+        CHECK(!newFramebufferWeak.expired());
+        CHECK(!newBufferWeak.expired());
+
+        std::vector<SPropertyWrite> expectedFrameProperties;
+        expectedFrameProperties.reserve(resolved.route->members().size() * 10U);
+        for (const auto& MEMBER : resolved.route->members())
+            appendFrameExpected(expectedFrameProperties, MEMBER, resolved.route->framebuffer().id);
+        CHECK(frameRecorder->properties == expectedFrameProperties);
+        CHECK(teardown(runtime, registry));
+        CHECK(newFramebufferWeak.expired());
+        CHECK(newBufferWeak.expired());
+    }
+
+    // 2. Submit failure rolls back both prepared runtime ownership and every
+    // reserved CRTC slot.
+    {
+        SFrameRuntime runtime(resolved.route->runtimePlan<PFrameOwner>());
+        const auto    oldBuffer = frameOwner(300);
+        CHECK(runtime.publishIdle(currentFrames(resolved.route, 800, 700, oldBuffer)));
+        CTiledFlipReservationRegistry registry;
+        auto                          frameRecorder                 = makeShared<SFrameRecorder>();
+        frameRecorder->runtime                                      = &runtime;
+        frameRecorder->registry                                     = &registry;
+        frameRecorder->observedCrtcId                               = resolved.route->crtcIds().front();
+        frameRecorder->submitResult                                 = -EBUSY;
+        CSharedPointer<ITiledAtomicFrameOperations> frameOperations = frameRecorder;
+
+        auto                                        failedFramebuffer     = frameOwner(301);
+        auto                                        failedBuffer          = frameOwner(302);
+        const std::weak_ptr<SFrameOwner>            failedFramebufferWeak = failedFramebuffer;
+        const std::weak_ptr<SFrameOwner>            failedBufferWeak      = failedBuffer;
+        auto                                        failedFrame = runtimeFrame(resolved.route->framebuffer().id, 701, std::move(failedFramebuffer), std::move(failedBuffer));
+
+        const auto transaction = submitTiledFrameTransaction(resolved.route, runtime, registry, std::move(failedFrame), 2'002, 60'000, 20, frameOperations);
+        CHECK(!static_cast<bool>(transaction));
+        CHECK(transaction.status == eTiledFrameTransactionStatus::SUBMISSION_FAILED);
+        CHECK(transaction.submission.has_value());
+        CHECK(transaction.submission.value_or(SAtomicSubmitResult{}).returnCode == -EBUSY);
+        CHECK(transaction.submission.value_or(SAtomicSubmitResult{}).error == EBUSY);
+        CHECK(transaction.effects.runtimePrepared);
+        CHECK(transaction.effects.reservationReserved);
+        CHECK(transaction.effects.reservationBound);
+        CHECK(transaction.effects.submitInvoked);
+        CHECK(!transaction.effects.kmsAccepted);
+        CHECK(!transaction.effects.runtimeAccepted);
+        CHECK(!transaction.effects.registryAccepted);
+        CHECK(transaction.effects.runtimeRolledBack);
+        CHECK(transaction.effects.registryRolledBack);
+        CHECK(runtime.state() == eTiledRuntimeState::PUBLISHED_IDLE);
+        CHECK(runtime.preparedRoute() == nullptr);
+        CHECK(registry.transactionCount() == 0);
+        CHECK(registry.claimedCrtcCount() == 0);
+        CHECK(registry.routeEvent(2'002, resolved.route->crtcIds().front()) == eTiledRouteEventResult::NOT_OWNED);
+        CHECK(frameRecorder->routeDuringSubmit == eTiledRouteEventResult::RESERVED);
+        CHECK(frameRecorder->submits == 1);
+        CHECK(frameRecorder->frees == 1);
+        CHECK(failedFramebufferWeak.expired());
+        CHECK(failedBufferWeak.expired());
+        CHECK(teardown(runtime, registry));
+    }
+
+    // 3. A conflicting member reservation prevents submit and leaves the
+    // existing all-member reservation unchanged.
+    {
+        SFrameRuntime runtime(resolved.route->runtimePlan<PFrameOwner>());
+        const auto    oldBuffer = frameOwner(400);
+        CHECK(runtime.publishIdle(currentFrames(resolved.route, 900, 800, oldBuffer)));
+        CTiledFlipReservationRegistry registry;
+        const STiledFlipRoute         blockingRoute{
+            .transactionId = 3'000,
+            .generation    = resolved.route->generation(),
+            .crtcIds       = {resolved.route->crtcIds().begin(), resolved.route->crtcIds().end()},
+        };
+        const auto blocker = registry.reserveAll(blockingRoute);
+        CHECK(static_cast<bool>(blocker));
+
+        auto                                        frameRecorder           = makeShared<SFrameRecorder>();
+        CSharedPointer<ITiledAtomicFrameOperations> frameOperations         = frameRecorder;
+        auto                                        collidedFramebuffer     = frameOwner(401);
+        auto                                        collidedBuffer          = frameOwner(402);
+        const std::weak_ptr<SFrameOwner>            collidedFramebufferWeak = collidedFramebuffer;
+        const std::weak_ptr<SFrameOwner>            collidedBufferWeak      = collidedBuffer;
+        auto                                        collidedFrame = runtimeFrame(resolved.route->framebuffer().id, 801, std::move(collidedFramebuffer), std::move(collidedBuffer));
+
+        const auto transaction = submitTiledFrameTransaction(resolved.route, runtime, registry, std::move(collidedFrame), 3'003, 70'000, 21, frameOperations);
+        CHECK(!static_cast<bool>(transaction));
+        CHECK(transaction.status == eTiledFrameTransactionStatus::RESERVATION_FAILED);
+        CHECK(transaction.reservationError == eTiledReservationError::CRTC_CONFLICT);
+        CHECK(transaction.effects.requestBuilt);
+        CHECK(transaction.effects.runtimePrepared);
+        CHECK(!transaction.effects.reservationReserved);
+        CHECK(!transaction.effects.reservationBound);
+        CHECK(!transaction.effects.submitInvoked);
+        CHECK(transaction.effects.runtimeRolledBack);
+        CHECK(!transaction.effects.registryRolledBack);
+        CHECK(runtime.state() == eTiledRuntimeState::PUBLISHED_IDLE);
+        CHECK(runtime.preparedRoute() == nullptr);
+        CHECK(registry.transactionCount() == 1);
+        CHECK(registry.claimedCrtcCount() == resolved.route->crtcIds().size());
+        CHECK(registry.matches(blocker.reservation, blockingRoute));
+        CHECK(frameRecorder->submits == 0);
+        CHECK(frameRecorder->frees == 1);
+        CHECK(collidedFramebufferWeak.expired());
+        CHECK(collidedBufferWeak.expired());
+        CHECK(registry.rollback(blocker.reservation));
+        CHECK(teardown(runtime, registry));
+    }
+
+    // 4. Events stay grouped until every member CRTC arrives; completion emits
+    // exactly one release for the shared old buffer identity.
+    {
+        SFrameRuntime                    runtime(resolved.route->runtimePlan<PFrameOwner>());
+        auto                             oldBuffer     = frameOwner(500);
+        const std::weak_ptr<SFrameOwner> oldBufferWeak = oldBuffer;
+        CHECK(runtime.publishIdle(currentFrames(resolved.route, 1'000, 900, oldBuffer)));
+        oldBuffer.reset();
+        CTiledFlipReservationRegistry registry;
+        auto                          frameRecorder                 = makeShared<SFrameRecorder>();
+        frameRecorder->runtime                                      = &runtime;
+        frameRecorder->registry                                     = &registry;
+        frameRecorder->observedCrtcId                               = resolved.route->crtcIds().front();
+        CSharedPointer<ITiledAtomicFrameOperations> frameOperations = frameRecorder;
+
+        auto                                        completedFramebuffer     = frameOwner(501);
+        auto                                        completedBuffer          = frameOwner(502);
+        const std::weak_ptr<SFrameOwner>            completedFramebufferWeak = completedFramebuffer;
+        const std::weak_ptr<SFrameOwner>            completedBufferWeak      = completedBuffer;
+        auto       completedFrame = runtimeFrame(resolved.route->framebuffer().id, 901, std::move(completedFramebuffer), std::move(completedBuffer));
+
+        const auto transaction = submitTiledFrameTransaction(resolved.route, runtime, registry, std::move(completedFrame), 4'004, 80'000, 22, frameOperations);
+        CHECK(static_cast<bool>(transaction));
+        CHECK(registry.routeEvent(4'004, resolved.route->crtcIds().front()) == eTiledRouteEventResult::ROUTABLE);
+        const auto firstEvent = runtime.record(4'004, resolved.route->crtcIds().front(), 10, 100);
+        CHECK(firstEvent.disposition == eTiledEventDisposition::RECORDED);
+        CHECK(!firstEvent.schedulerComplete);
+        CHECK(firstEvent.releases.empty());
+
+        CHECK(registry.routeEvent(4'004, resolved.route->crtcIds().back()) == eTiledRouteEventResult::ROUTABLE);
+        auto completion = runtime.record(4'004, resolved.route->crtcIds().back(), 20, 120);
+        CHECK(completion.disposition == eTiledEventDisposition::COMPLETED);
+        CHECK(completion.schedulerComplete);
+        CHECK(completion.present);
+        CHECK(completion.retireReservation);
+        CHECK(completion.reservation == transaction.effects.reservation);
+        CHECK(completion.releases.size() == 1);
+        CHECK(completion.releases.front().bufferId == 900);
+        CHECK(completion.releases.front().owner == oldBufferWeak.lock());
+        CHECK(registry.retire(completion.reservation.value_or(STiledFlipReservation{})));
+        CHECK(registry.transactionCount() == 0);
+        CHECK(registry.claimedCrtcCount() == 0);
+        CHECK(runtime.state() == eTiledRuntimeState::PUBLISHED_IDLE);
+        CHECK(runtime.currentFrames().size() == 1);
+        CHECK(runtime.currentFrames().front().framebufferId == resolved.route->framebuffer().id);
+        CHECK(runtime.currentFrames().front().bufferId == 901);
+        CHECK(!completedFramebufferWeak.expired());
+        CHECK(!completedBufferWeak.expired());
+        completion.releases.clear();
+        CHECK(teardown(runtime, registry));
+        CHECK(oldBufferWeak.expired());
+        CHECK(completedFramebufferWeak.expired());
+        CHECK(completedBufferWeak.expired());
+    }
+
     return FAILURES == 0 ? 0 : 1;
 }