From c8dd371dceb1df996fac374fb1aded331972fc62 Mon Sep 17 00:00:00 2001
From: Justin Youens <justin@youens.com>
Date: Mon, 24 Aug 2026 21:37:30 -0500
Subject: [PATCH] drm: validate tiled groups before suppressing connectors

The redundant-tile heuristic trusted the first member's TILE geometry
and compared independent maximum mode dimensions. An incomplete or
inconsistent group could therefore hide usable connectors, and maxima
from different modes could look like an aggregate mode.

Parse the length-delimited blob strictly, validate a complete and
consistent tile grid, and only suppress when exactly one connector
advertises the exact aggregate mode. Fail open on malformed, incomplete,
ambiguous, or unreadable groups.

Keep the helpers source-private and cover parser and topology edge
cases.
---
 CMakeLists.txt             |   8 ++
 src/backend/drm/DRM.cpp    | 103 ++++++++++++++--------
 src/backend/drm/Tiling.cpp | 131 ++++++++++++++++++++++++++++
 src/backend/drm/Tiling.hpp |  36 ++++++++
 tests/DRMTiling.cpp        | 169 +++++++++++++++++++++++++++++++++++++
 5 files changed, 410 insertions(+), 37 deletions(-)
 create mode 100644 src/backend/drm/Tiling.cpp
 create mode 100644 src/backend/drm/Tiling.hpp
 create mode 100644 tests/DRMTiling.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e501f83..bd46263 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -168,6 +168,14 @@ add_test(
   COMMAND commitThread "commitThread")
 add_dependencies(tests commitThread)
 
+add_executable(drmTiling "tests/DRMTiling.cpp" "src/backend/drm/Tiling.cpp")
+target_include_directories(drmTiling PRIVATE "./src/backend/drm")
+add_test(
+  NAME "drmTiling"
+  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests
+  COMMAND drmTiling "drmTiling")
+add_dependencies(tests drmTiling)
+
 # Installation
 install(TARGETS aquamarine)
 install(DIRECTORY "include/aquamarine" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp
index 6618a26..7471a76 100644
--- a/src/backend/drm/DRM.cpp
+++ b/src/backend/drm/DRM.cpp
@@ -6,6 +6,7 @@
 #include <aquamarine/allocator/GBM.hpp>
 #include <aquamarine/allocator/DRMDumb.hpp>
 #include <cstdint>
+#include <cstdlib>
 #include <format>
 #include <hyprutils/math/Mat3x3.hpp>
 #include <hyprutils/memory/Atomic.hpp>
@@ -16,6 +17,7 @@
 #include <unordered_map>
 #include <cstring>
 #include <filesystem>
+#include <memory>
 #include <system_error>
 #include <utility>
 #include <sys/mman.h>
@@ -39,6 +41,7 @@ extern "C" {
 #include "Renderer.hpp"
 #include "OutputTiming.hpp"
 #include "AsyncCommit.hpp"
+#include "Tiling.hpp"
 
 #include <hyprutils/utils/ScopeGuard.hpp>
 using Hyprutils::Utils::CScopeGuard;
@@ -1155,6 +1158,44 @@ eBackendType Aquamarine::CDRMBackend::type() {
     return eBackendType::AQ_BACKEND_DRM;
 }
 
+static std::optional<NDRM::STileGroup> validatedTileGroup(int fd, const std::vector<SP<SDRMConnector>>& members) {
+    std::vector<NDRM::STileConnector> tiles;
+    tiles.reserve(members.size());
+
+    for (const auto& conn : members) {
+        NDRM::STileConnector tile = {
+            .connectorId = conn->id,
+            .tile =
+                {
+                    .groupId         = conn->tileInfo.groupId,
+                    .isSingleMonitor = conn->tileInfo.isSingleMonitor,
+                    .numHTile        = static_cast<uint32_t>(conn->tileInfo.numHTile),
+                    .numVTile        = static_cast<uint32_t>(conn->tileInfo.numVTile),
+                    .tileHLoc        = static_cast<uint32_t>(conn->tileInfo.tileHLoc),
+                    .tileVLoc        = static_cast<uint32_t>(conn->tileInfo.tileVLoc),
+                    .tileHSize       = static_cast<uint32_t>(conn->tileInfo.tileHSize),
+                    .tileVSize       = static_cast<uint32_t>(conn->tileInfo.tileVSize),
+                },
+        };
+
+        auto drmConn = drmModeGetConnectorCurrent(fd, conn->id);
+        if (!drmConn || drmConn->connection != DRM_MODE_CONNECTED) {
+            if (drmConn)
+                drmModeFreeConnector(drmConn);
+            return std::nullopt;
+        }
+
+        tile.modes.reserve(drmConn->count_modes);
+        for (int i = 0; i < drmConn->count_modes; ++i)
+            tile.modes.emplace_back(NDRM::STileMode{.width = drmConn->modes[i].hdisplay, .height = drmConn->modes[i].vdisplay});
+        drmModeFreeConnector(drmConn);
+
+        tiles.emplace_back(std::move(tile));
+    }
+
+    return NDRM::validateTileGroup(tiles);
+}
+
 void Aquamarine::CDRMBackend::markRedundantTiles() {
     for (const auto& conn : connectors) {
         conn->parseTileInfo();
@@ -1172,32 +1213,25 @@ void Aquamarine::CDRMBackend::markRedundantTiles() {
         if (members.size() <= 1)
             continue;
 
-        const auto& ti         = members.at(0)->tileInfo;
-        int         fullWidth  = ti.numHTile * ti.tileHSize;
-        int         fullHeight = ti.numVTile * ti.tileVSize;
-
-        backend->log(AQ_LOG_DEBUG, std::format("drm: Tile group {} has {} members, full tiled resolution {}x{}", groupId, members.size(), fullWidth, fullHeight));
-
-        // check if any single connector already has the full tiled resolution,
-        // meaning the driver handles tiling internally
-        SP<SDRMConnector> fullResConn;
-        for (const auto& conn : members) {
-            if (conn->maxMode.x >= fullWidth && conn->maxMode.y >= fullHeight) {
-                fullResConn = conn;
-                break;
-            }
+        const auto GROUP = validatedTileGroup(gpu->fd, members);
+        if (!GROUP) {
+            backend->log(AQ_LOG_DEBUG, std::format("drm: Not suppressing invalid, incomplete, or unreadable tile group {}", groupId));
+            continue;
         }
 
-        if (!fullResConn)
+        backend->log(AQ_LOG_DEBUG, std::format("drm: Tile group {} has {} members, full tiled resolution {}x{}", groupId, members.size(), GROUP->width, GROUP->height));
+
+        if (GROUP->fullModeConnector == 0)
             continue;
 
         for (const auto& conn : members) {
-            if (conn == fullResConn)
+            if (conn->id == GROUP->fullModeConnector)
                 continue;
 
             conn->tilingRedundant = true;
-            backend->log(AQ_LOG_DEBUG,
-                         std::format("drm: Connector {} marked as tiling redundant (tile group {}, driver-managed by {})", conn->szName, groupId, fullResConn->szName));
+            backend->log(
+                AQ_LOG_DEBUG,
+                std::format("drm: Connector {} marked as tiling redundant (tile group {}, aggregate mode on connector {})", conn->szName, groupId, GROUP->fullModeConnector));
         }
     }
 }
@@ -1792,30 +1826,25 @@ void Aquamarine::SDRMConnector::parseTileInfo() {
         return;
 
     size_t blobLen  = 0;
-    char*  blobData = (char*)getDRMPropBlob(backend->gpu->fd, id, props.values.tile, &blobLen);
-    if (!blobData || blobLen == 0) {
-        free(blobData);
+    auto   blobData = std::unique_ptr<char, decltype(&std::free)>{static_cast<char*>(getDRMPropBlob(backend->gpu->fd, id, props.values.tile, &blobLen)), &std::free};
+    if (!blobData || blobLen == 0)
         return;
-    }
 
-    // TILE blob is a text string: "group_id:is_single_monitor:num_h:num_v:h_loc:v_loc:h_size:v_size"
-    uint32_t groupId         = 0;
-    int      isSingleMonitor = 0, numH = 0, numV = 0, hLoc = 0, vLoc = 0, hSize = 0, vSize = 0;
-    if (sscanf(blobData, "%u:%d:%d:%d:%d:%d:%d:%d", &groupId, &isSingleMonitor, &numH, &numV, &hLoc, &vLoc, &hSize, &vSize) == 8 && groupId != 0) {
-        tileInfo.groupId         = groupId;
-        tileInfo.isSingleMonitor = isSingleMonitor != 0;
-        tileInfo.numHTile        = numH;
-        tileInfo.numVTile        = numV;
-        tileInfo.tileHLoc        = hLoc;
-        tileInfo.tileVLoc        = vLoc;
-        tileInfo.tileHSize       = hSize;
-        tileInfo.tileVSize       = vSize;
+    const auto PARSED = NDRM::parseTileInfo(std::string_view{blobData.get(), blobLen});
+    if (PARSED) {
+        tileInfo.groupId         = PARSED->groupId;
+        tileInfo.isSingleMonitor = PARSED->isSingleMonitor;
+        tileInfo.numHTile        = static_cast<int>(PARSED->numHTile);
+        tileInfo.numVTile        = static_cast<int>(PARSED->numVTile);
+        tileInfo.tileHLoc        = static_cast<int>(PARSED->tileHLoc);
+        tileInfo.tileVLoc        = static_cast<int>(PARSED->tileVLoc);
+        tileInfo.tileHSize       = static_cast<int>(PARSED->tileHSize);
+        tileInfo.tileVSize       = static_cast<int>(PARSED->tileVSize);
 
         backend->backend->log(AQ_LOG_DEBUG,
-                              std::format("drm: Connector {} tile info: group={} tiles={}x{} pos=({},{}) size={}x{}", szName, groupId, numH, numV, hLoc, vLoc, hSize, vSize));
+                              std::format("drm: Connector {} tile info: group={} tiles={}x{} pos=({},{}) size={}x{}", szName, tileInfo.groupId, tileInfo.numHTile,
+                                          tileInfo.numVTile, tileInfo.tileHLoc, tileInfo.tileVLoc, tileInfo.tileHSize, tileInfo.tileVSize));
     }
-
-    free(blobData);
 }
 
 void Aquamarine::SDRMConnector::releaseFBBuffer(const SP<CDRMFB> fb) {
diff --git a/src/backend/drm/Tiling.cpp b/src/backend/drm/Tiling.cpp
new file mode 100644
index 0000000..7eb5bff
--- /dev/null
+++ b/src/backend/drm/Tiling.cpp
@@ -0,0 +1,131 @@
+#include "Tiling.hpp"
+
+#include <array>
+#include <charconv>
+#include <limits>
+#include <set>
+#include <utility>
+
+using namespace Aquamarine::NDRM;
+
+std::optional<STileInfo> Aquamarine::NDRM::parseTileInfo(std::string_view blob) {
+    if (blob.ends_with('\0'))
+        blob.remove_suffix(1);
+
+    if (blob.contains('\0'))
+        return std::nullopt;
+
+    std::array<uint32_t, 8> values = {};
+    size_t                  begin  = 0;
+
+    for (size_t i = 0; i < values.size(); ++i) {
+        const auto END = blob.find(':', begin);
+        if ((i + 1 < values.size() && END == std::string_view::npos) || (i + 1 == values.size() && END != std::string_view::npos))
+            return std::nullopt;
+
+        const auto TOKEN_END = END == std::string_view::npos ? blob.size() : END;
+        if (TOKEN_END == begin)
+            return std::nullopt;
+
+        const auto TOKEN  = blob.substr(begin, TOKEN_END - begin);
+        const auto RESULT = std::from_chars(TOKEN.data(), TOKEN.data() + TOKEN.size(), values.at(i));
+        if (RESULT.ec != std::errc{} || RESULT.ptr != TOKEN.data() + TOKEN.size())
+            return std::nullopt;
+
+        begin = TOKEN_END + 1;
+    }
+
+    if (values.at(0) == 0 || values.at(0) > static_cast<uint32_t>(std::numeric_limits<int>::max()) || values.at(1) > 1)
+        return std::nullopt;
+
+    for (size_t i = 2; i < values.size(); ++i) {
+        if (values.at(i) > static_cast<uint32_t>(std::numeric_limits<int>::max()))
+            return std::nullopt;
+    }
+
+    STileInfo tile = {
+        .groupId         = values.at(0),
+        .isSingleMonitor = values.at(1) != 0,
+        .numHTile        = values.at(2),
+        .numVTile        = values.at(3),
+        .tileHLoc        = values.at(4),
+        .tileVLoc        = values.at(5),
+        .tileHSize       = values.at(6),
+        .tileVSize       = values.at(7),
+    };
+
+    if (tile.numHTile == 0 || tile.numVTile == 0 || tile.tileHLoc >= tile.numHTile || tile.tileVLoc >= tile.numVTile || tile.tileHSize == 0 || tile.tileVSize == 0)
+        return std::nullopt;
+
+    return tile;
+}
+
+std::optional<STileGroup> Aquamarine::NDRM::validateTileGroup(std::span<const STileConnector> connectors) {
+    if (connectors.empty())
+        return std::nullopt;
+
+    const auto& FIRST = connectors.front().tile;
+    if (FIRST.groupId == 0 || FIRST.numHTile == 0 || FIRST.numVTile == 0)
+        return std::nullopt;
+
+    const uint64_t EXPECTED_MEMBERS = static_cast<uint64_t>(FIRST.numHTile) * FIRST.numVTile;
+    if (EXPECTED_MEMBERS != connectors.size())
+        return std::nullopt;
+
+    std::set<uint32_t>                      connectorIds;
+    std::set<std::pair<uint32_t, uint32_t>> locations;
+    std::vector<uint32_t>                   columnWidths(FIRST.numHTile);
+    std::vector<uint32_t>                   rowHeights(FIRST.numVTile);
+
+    for (const auto& CONNECTOR : connectors) {
+        const auto& TILE = CONNECTOR.tile;
+        if (CONNECTOR.connectorId == 0 || !connectorIds.emplace(CONNECTOR.connectorId).second || TILE.groupId != FIRST.groupId || TILE.isSingleMonitor != FIRST.isSingleMonitor ||
+            TILE.numHTile != FIRST.numHTile || TILE.numVTile != FIRST.numVTile || TILE.tileHLoc >= FIRST.numHTile || TILE.tileVLoc >= FIRST.numVTile || TILE.tileHSize == 0 ||
+            TILE.tileVSize == 0 || !locations.emplace(TILE.tileVLoc, TILE.tileHLoc).second)
+            return std::nullopt;
+
+        auto& columnWidth = columnWidths.at(TILE.tileHLoc);
+        auto& rowHeight   = rowHeights.at(TILE.tileVLoc);
+        if ((columnWidth != 0 && columnWidth != TILE.tileHSize) || (rowHeight != 0 && rowHeight != TILE.tileVSize))
+            return std::nullopt;
+
+        columnWidth = TILE.tileHSize;
+        rowHeight   = TILE.tileVSize;
+    }
+
+    uint64_t width = 0, height = 0;
+    for (const auto WIDTH : columnWidths)
+        width += WIDTH;
+    for (const auto HEIGHT : rowHeights)
+        height += HEIGHT;
+
+    if (width == 0 || height == 0 || width > std::numeric_limits<uint32_t>::max() || height > std::numeric_limits<uint32_t>::max())
+        return std::nullopt;
+
+    uint32_t fullModeConnector = 0;
+    bool     ambiguousFullMode = false;
+
+    for (const auto& CONNECTOR : connectors) {
+        bool hasFullMode = false;
+        for (const auto& MODE : CONNECTOR.modes) {
+            if (MODE.width == width && MODE.height == height) {
+                hasFullMode = true;
+                break;
+            }
+        }
+
+        if (!hasFullMode)
+            continue;
+
+        if (fullModeConnector != 0)
+            ambiguousFullMode = true;
+        else
+            fullModeConnector = CONNECTOR.connectorId;
+    }
+
+    return STileGroup{
+        .width             = static_cast<uint32_t>(width),
+        .height            = static_cast<uint32_t>(height),
+        .fullModeConnector = ambiguousFullMode ? 0U : fullModeConnector,
+    };
+}
diff --git a/src/backend/drm/Tiling.hpp b/src/backend/drm/Tiling.hpp
new file mode 100644
index 0000000..468d27e
--- /dev/null
+++ b/src/backend/drm/Tiling.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <cstdint>
+#include <optional>
+#include <span>
+#include <string_view>
+#include <vector>
+
+namespace Aquamarine::NDRM {
+    struct [[gnu::visibility("hidden")]] STileInfo {
+        uint32_t groupId         = 0;
+        bool     isSingleMonitor = false;
+        uint32_t numHTile = 0, numVTile = 0;
+        uint32_t tileHLoc = 0, tileVLoc = 0;
+        uint32_t tileHSize = 0, tileVSize = 0;
+    };
+
+    struct [[gnu::visibility("hidden")]] STileMode {
+        uint32_t width = 0, height = 0;
+    };
+
+    struct [[gnu::visibility("hidden")]] STileConnector {
+        uint32_t               connectorId = 0;
+        STileInfo              tile;
+        std::vector<STileMode> modes;
+    };
+
+    struct [[gnu::visibility("hidden")]] STileGroup {
+        uint32_t width             = 0;
+        uint32_t height            = 0;
+        uint32_t fullModeConnector = 0;
+    };
+
+    [[gnu::visibility("hidden")]] std::optional<STileInfo>  parseTileInfo(std::string_view blob);
+    [[gnu::visibility("hidden")]] std::optional<STileGroup> validateTileGroup(std::span<const STileConnector> connectors);
+}
diff --git a/tests/DRMTiling.cpp b/tests/DRMTiling.cpp
new file mode 100644
index 0000000..bf2d4e6
--- /dev/null
+++ b/tests/DRMTiling.cpp
@@ -0,0 +1,169 @@
+#include "Tiling.hpp"
+#include "shared.hpp"
+
+#include <array>
+#include <limits>
+#include <utility>
+
+using namespace Aquamarine::NDRM;
+
+static STileInfo tile(uint32_t groupId, uint32_t columns, uint32_t rows, uint32_t column, uint32_t row, uint32_t width, uint32_t height, bool singleMonitor = true) {
+    return STileInfo{
+        .groupId         = groupId,
+        .isSingleMonitor = singleMonitor,
+        .numHTile        = columns,
+        .numVTile        = rows,
+        .tileHLoc        = column,
+        .tileVLoc        = row,
+        .tileHSize       = width,
+        .tileVSize       = height,
+    };
+}
+
+static STileConnector connector(uint32_t id, STileInfo info, std::vector<STileMode> modes = {}) {
+    return STileConnector{.connectorId = id, .tile = info, .modes = std::move(modes)};
+}
+
+static STileMode mode(uint32_t width, uint32_t height) {
+    return STileMode{.width = width, .height = height};
+}
+
+int main() {
+    int        ret = 0;
+
+    const auto PARSED = parseTileInfo("1:1:2:1:0:0:2560:2880");
+    EXPECT(PARSED.has_value(), true);
+    if (!PARSED)
+        return 1;
+    EXPECT(PARSED->groupId, 1U);
+    EXPECT(PARSED->isSingleMonitor, true);
+    EXPECT(PARSED->numHTile, 2U);
+    EXPECT(PARSED->tileHSize, 2560U);
+
+    const std::array<char, 22> NUL_TERMINATED = {'2', ':', '0', ':', '1', ':', '2', ':', '0', ':', '1', ':', '3', '8', '4', '0', ':', '2', '1', '6', '0', '\0'};
+    const auto                 PARSED_NUL     = parseTileInfo(std::string_view{NUL_TERMINATED.data(), NUL_TERMINATED.size()});
+    EXPECT(PARSED_NUL.has_value(), true);
+    if (!PARSED_NUL)
+        return 1;
+    EXPECT(PARSED_NUL->groupId, 2U);
+    EXPECT(PARSED_NUL->isSingleMonitor, false);
+    EXPECT(PARSED_NUL->tileVLoc, 1U);
+
+    const auto invalid = [](std::string_view value) { return !parseTileInfo(value).has_value(); };
+    EXPECT(invalid(""), true);
+    EXPECT(invalid("1:1:2:1:0:0:2560"), true);
+    EXPECT(invalid("1:1:2:1:0:0:2560:2880:0"), true);
+    EXPECT(invalid("1:1:two:1:0:0:2560:2880"), true);
+    EXPECT(invalid("1:1:-2:1:0:0:2560:2880"), true);
+    EXPECT(invalid("4294967296:1:2:1:0:0:2560:2880"), true);
+    EXPECT(invalid("2147483648:1:2:1:0:0:2560:2880"), true);
+    EXPECT(invalid("0:1:2:1:0:0:2560:2880"), true);
+    EXPECT(invalid("1:2:2:1:0:0:2560:2880"), true);
+    EXPECT(invalid("1:1:0:1:0:0:2560:2880"), true);
+    EXPECT(invalid("1:1:2:1:2:0:2560:2880"), true);
+    EXPECT(invalid("1:1:2:1:0:0:0:2880"), true);
+    EXPECT(invalid("1:1:2:1:0:0:2147483648:2880"), true);
+
+    const std::array<char, 23> EMBEDDED_NUL = {'2', ':', '0', ':', '1', ':', '2', ':', '0', ':', '1', ':', '3', '8', '4', '0', ':', '2', '1', '6', '0', '\0', 'x'};
+    EXPECT(invalid(std::string_view{EMBEDDED_NUL.data(), EMBEDDED_NUL.size()}), true);
+
+    std::vector<STileConnector> lg = {
+        connector(202, tile(1, 2, 1, 1, 0, 2560, 2880), {mode(2560, 2880)}),
+        connector(101, tile(1, 2, 1, 0, 0, 2560, 2880), {mode(2560, 2880), mode(5120, 2880)}),
+    };
+
+    const auto LG = validateTileGroup(lg);
+    EXPECT(LG.has_value(), true);
+    if (!LG)
+        return 1;
+    EXPECT(LG->width, 5120U);
+    EXPECT(LG->height, 2880U);
+    EXPECT(LG->fullModeConnector, 101U);
+
+    auto noCombinedPair        = lg;
+    noCombinedPair.at(1).modes = {mode(5120, 1440), mode(3840, 2880)};
+    const auto NO_PAIR         = validateTileGroup(noCombinedPair);
+    EXPECT(NO_PAIR.has_value(), true);
+    if (!NO_PAIR)
+        return 1;
+    EXPECT(NO_PAIR->fullModeConnector, 0U);
+
+    auto largerMode        = lg;
+    largerMode.at(1).modes = {mode(5120, 3000)};
+    const auto LARGER_MODE = validateTileGroup(largerMode);
+    EXPECT(LARGER_MODE.has_value(), true);
+    if (!LARGER_MODE)
+        return 1;
+    EXPECT(LARGER_MODE->fullModeConnector, 0U);
+
+    auto ambiguous = lg;
+    ambiguous.at(0).modes.emplace_back(mode(5120, 2880));
+    const auto AMBIGUOUS = validateTileGroup(ambiguous);
+    EXPECT(AMBIGUOUS.has_value(), true);
+    if (!AMBIGUOUS)
+        return 1;
+    EXPECT(AMBIGUOUS->fullModeConnector, 0U);
+
+    EXPECT(validateTileGroup(std::span<const STileConnector>{lg}.first(1)).has_value(), false);
+
+    auto inconsistentGrid                = lg;
+    inconsistentGrid.at(1).tile.numHTile = 3;
+    EXPECT(validateTileGroup(inconsistentGrid).has_value(), false);
+
+    auto inconsistentMonitor                       = lg;
+    inconsistentMonitor.at(1).tile.isSingleMonitor = false;
+    EXPECT(validateTileGroup(inconsistentMonitor).has_value(), false);
+
+    auto multiHousingGroup = lg;
+    for (auto& connector : multiHousingGroup)
+        connector.tile.isSingleMonitor = false;
+    const auto MULTI_HOUSING_GROUP = validateTileGroup(multiHousingGroup);
+    EXPECT(MULTI_HOUSING_GROUP.has_value(), true);
+    if (!MULTI_HOUSING_GROUP)
+        return 1;
+    EXPECT(MULTI_HOUSING_GROUP->fullModeConnector, 101U);
+
+    auto inconsistentGroup               = lg;
+    inconsistentGroup.at(1).tile.groupId = 2;
+    EXPECT(validateTileGroup(inconsistentGroup).has_value(), false);
+
+    auto zeroConnector              = lg;
+    zeroConnector.at(0).connectorId = 0;
+    EXPECT(validateTileGroup(zeroConnector).has_value(), false);
+
+    auto duplicateLocation                = lg;
+    duplicateLocation.at(0).tile.tileHLoc = 0;
+    EXPECT(validateTileGroup(duplicateLocation).has_value(), false);
+
+    auto duplicateConnector              = lg;
+    duplicateConnector.at(0).connectorId = 101;
+    EXPECT(validateTileGroup(duplicateConnector).has_value(), false);
+
+    std::vector<STileConnector> nonuniform = {
+        connector(11, tile(2, 2, 2, 0, 0, 1920, 1080)),
+        connector(22, tile(2, 2, 2, 1, 0, 2560, 1080)),
+        connector(33, tile(2, 2, 2, 0, 1, 1920, 1200)),
+        connector(44, tile(2, 2, 2, 1, 1, 2560, 1200), {mode(4480, 2280)}),
+    };
+    const auto NONUNIFORM = validateTileGroup(nonuniform);
+    EXPECT(NONUNIFORM.has_value(), true);
+    if (!NONUNIFORM)
+        return 1;
+    EXPECT(NONUNIFORM->width, 4480U);
+    EXPECT(NONUNIFORM->height, 2280U);
+    EXPECT(NONUNIFORM->fullModeConnector, 44U);
+
+    auto inconsistentGeometry                 = nonuniform;
+    inconsistentGeometry.at(2).tile.tileHSize = 1919;
+    EXPECT(validateTileGroup(inconsistentGeometry).has_value(), false);
+
+    const auto                        MAX_TILE_WIDTH = static_cast<uint32_t>(std::numeric_limits<int>::max());
+    const std::vector<STileConnector> overflowing    = {
+        connector(51, tile(3, 3, 1, 0, 0, MAX_TILE_WIDTH, 1)),
+        connector(52, tile(3, 3, 1, 1, 0, MAX_TILE_WIDTH, 1)),
+        connector(53, tile(3, 3, 1, 2, 0, MAX_TILE_WIDTH, 1)),
+    };
+    EXPECT(validateTileGroup(overflowing).has_value(), false);
+
+    return ret;
+}
-- 
2.55.0

