Show a patch.

GET /api/patches/22290/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 22290,
    "url": "https://patchwork.libcamera.org/api/patches/22290/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/22290/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20241211152542.1095857-3-pobrn@protonmail.com>",
    "date": "2024-12-11T15:25:56",
    "name": "[v1,3/3] libcamera: virtual: Speed up test pattern animation",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "09836df5b14ce989e910e18b20171b53b81cdfff",
    "submitter": {
        "id": 133,
        "url": "https://patchwork.libcamera.org/api/people/133/?format=api",
        "name": "Pőcze Barnabás",
        "email": "pobrn@protonmail.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/22290/mbox/",
    "series": [
        {
            "id": 4874,
            "url": "https://patchwork.libcamera.org/api/series/4874/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4874",
            "date": "2024-12-11T15:25:45",
            "name": "[v1,1/3] libcamera: virtual: Avoid some copies",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/4874/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/22290/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/22290/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>",
        "X-Original-To": "parsemail@patchwork.libcamera.org",
        "Delivered-To": "parsemail@patchwork.libcamera.org",
        "Received": [
            "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 11232BD80A\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 11 Dec 2024 15:26:06 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id BAA5E67EBA;\n\tWed, 11 Dec 2024 16:26:05 +0100 (CET)",
            "from mail-40133.protonmail.ch (mail-40133.protonmail.ch\n\t[185.70.40.133])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C0E9B67EB1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 11 Dec 2024 16:26:03 +0100 (CET)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=protonmail.com header.i=@protonmail.com\n\theader.b=\"WgfVUf/j\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;\n\ts=protonmail3; t=1733930763; x=1734189963;\n\tbh=uLrSfwP4FXc2HR+sNpRAijAkImv9mgf1ETXXrtpNPdk=;\n\th=Date:To:From:Subject:Message-ID:In-Reply-To:References:\n\tFeedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID:\n\tMessage-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post;\n\tb=WgfVUf/jqoqOfowK9oVJ/jd9m7uJ3LJUaXxfsJ02a7ASdPFpNz/lYzG2sI9x3VJdb\n\tQbQWzgf/kQ+uYUwoe4YVo+Zs9QlCnqaLZGDBu5eiAbXQttnRtfG2kSAxuT2TE3UEm+\n\thYhZAdV9JcN5hVf5QZU1BvjVckcMPvsh28lJYIsBh2rfi0tVKtXE3N1c0ghoEmenXL\n\ttX4es1F7CaS/VIBk6j/0fuO25d6/wnpJ2FIi7CJNgdfjdLvTBxH/pepgntz/OdtEHP\n\tOgfyoj9Wk/xHh0mmbL6OC4LsJVa4DNNIMy4KMXWXIAJHcDDJ1wk6n+j1x+3PCvuXB4\n\tC4segC6kk/38A==",
        "Date": "Wed, 11 Dec 2024 15:25:56 +0000",
        "To": "libcamera-devel@lists.libcamera.org",
        "From": "=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <pobrn@protonmail.com>",
        "Subject": "[PATCH v1 3/3] libcamera: virtual: Speed up test pattern animation",
        "Message-ID": "<20241211152542.1095857-3-pobrn@protonmail.com>",
        "In-Reply-To": "<20241211152542.1095857-1-pobrn@protonmail.com>",
        "References": "<20241211152542.1095857-1-pobrn@protonmail.com>",
        "Feedback-ID": "20568564:user:proton",
        "X-Pm-Message-ID": "869d255ffcfb0670811601ba1af026beb2cf5323",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=utf-8",
        "Content-Transfer-Encoding": "quoted-printable",
        "X-BeenThere": "libcamera-devel@lists.libcamera.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "<libcamera-devel.lists.libcamera.org>",
        "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>",
        "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>",
        "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>",
        "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "After the initial generation, when a frame is requested,\nthe test pattern generator rotates the image left by 1 column.\n\nThe current approach has two shortcomings:\n  (1) it allocates a temporary buffer to hold one column;\n  (2) it swaps two columns at a time.\n\nThe test patterns are simple ARGB images, in row-major order,\nso doing (2) works against memory prefetching. This can be\naddressed by doing the rotation one row at a time as that way\nthe image is addressed in a purely linear fashion. Doing so also\neliminates the need for a dynamically allocated temporary buffer,\nas the required buffer now only needs to hold one sample,\nwhich is 4 bytes in this case.\n\nIn an optimized build, this results in about a 2x increase in the\nnumber of frames per second as reported by `cam`. In an unoptimized,\nASAN and UBSAN intrumented build, the difference is even bigger,\nwhich is useful for running lc-compliance in CI in a reasonable time.\n\nSigned-off-by: Barnabás Pőcze <pobrn@protonmail.com>\n---\n .../virtual/test_pattern_generator.cpp        | 68 +++++++++----------\n .../pipeline/virtual/test_pattern_generator.h |  4 --\n 2 files changed, 34 insertions(+), 38 deletions(-)",
    "diff": "diff --git a/src/libcamera/pipeline/virtual/test_pattern_generator.cpp b/src/libcamera/pipeline/virtual/test_pattern_generator.cpp\nindex 47d341919..eeadc1646 100644\n--- a/src/libcamera/pipeline/virtual/test_pattern_generator.cpp\n+++ b/src/libcamera/pipeline/virtual/test_pattern_generator.cpp\n@@ -5,6 +5,8 @@\n  * Derived class of FrameGenerator for generating test patterns\n  */\n \n+#include <string.h>\n+\n #include \"test_pattern_generator.h\"\n \n #include <libcamera/base/log.h>\n@@ -13,6 +15,37 @@\n \n #include <libyuv/convert_from_argb.h>\n \n+namespace {\n+\n+template<size_t SampleSize>\n+void rotateLeft1Sample(uint8_t *samples, size_t width)\n+{\n+\tif (width <= 0)\n+\t\treturn;\n+\n+\tconst size_t stride = width * SampleSize;\n+\tuint8_t first[SampleSize];\n+\n+\tmemcpy(first, &samples[0], SampleSize);\n+\tfor (size_t i = 0; i < stride - SampleSize; i += SampleSize)\n+\t\tmemcpy(&samples[i], &samples[i + SampleSize], SampleSize);\n+\tmemcpy(&samples[stride - SampleSize], first, SampleSize);\n+}\n+\n+template<size_t SampleSize>\n+void rotateLeft1Column(const libcamera::Size &size, uint8_t *image)\n+{\n+\tif (size.width < 2)\n+\t\treturn;\n+\n+\tconst size_t stride = size.width * SampleSize;\n+\n+\tfor (size_t i = 0; i < size.height; i++, image += stride)\n+\t\trotateLeft1Sample<SampleSize>(image, size.width);\n+}\n+\n+}\n+\n namespace libcamera {\n \n LOG_DECLARE_CATEGORY(Virtual)\n@@ -27,7 +60,7 @@ int TestPatternGenerator::generateFrame(const Size &size,\n \n \tconst auto &planes = mappedFrameBuffer.planes();\n \n-\tshiftLeft(size);\n+\trotateLeft1Column<kARGBSize>(size, template_.get());\n \n \t/* Convert the template_ to the frame buffer */\n \tint ret = libyuv::ARGBToNV12(template_.get(), size.width * kARGBSize,\n@@ -40,39 +73,6 @@ int TestPatternGenerator::generateFrame(const Size &size,\n \treturn ret;\n }\n \n-void TestPatternGenerator::shiftLeft(const Size &size)\n-{\n-\t/* Store the first column temporarily */\n-\tauto firstColumn = std::make_unique<uint8_t[]>(size.height * kARGBSize);\n-\tfor (size_t h = 0; h < size.height; h++) {\n-\t\tunsigned int index = h * size.width * kARGBSize;\n-\t\tunsigned int index1 = h * kARGBSize;\n-\t\tfirstColumn[index1] = template_[index];\n-\t\tfirstColumn[index1 + 1] = template_[index + 1];\n-\t\tfirstColumn[index1 + 2] = template_[index + 2];\n-\t\tfirstColumn[index1 + 3] = 0x00;\n-\t}\n-\n-\t/* Overwrite template_ */\n-\tuint8_t *buf = template_.get();\n-\tfor (size_t h = 0; h < size.height; h++) {\n-\t\tfor (size_t w = 0; w < size.width - 1; w++) {\n-\t\t\t/* Overwrite with the pixel on the right */\n-\t\t\tunsigned int index = (h * size.width + w + 1) * kARGBSize;\n-\t\t\t*buf++ = template_[index]; /* B */\n-\t\t\t*buf++ = template_[index + 1]; /* G */\n-\t\t\t*buf++ = template_[index + 2]; /* R */\n-\t\t\t*buf++ = 0x00; /* A */\n-\t\t}\n-\t\t/* Overwrite the new last column with the original first column */\n-\t\tunsigned int index1 = h * kARGBSize;\n-\t\t*buf++ = firstColumn[index1]; /* B */\n-\t\t*buf++ = firstColumn[index1 + 1]; /* G */\n-\t\t*buf++ = firstColumn[index1 + 2]; /* R */\n-\t\t*buf++ = 0x00; /* A */\n-\t}\n-}\n-\n void ColorBarsGenerator::configure(const Size &size)\n {\n \tconstexpr uint8_t kColorBar[8][3] = {\ndiff --git a/src/libcamera/pipeline/virtual/test_pattern_generator.h b/src/libcamera/pipeline/virtual/test_pattern_generator.h\nindex 05f4ab7a7..2a51bd31a 100644\n--- a/src/libcamera/pipeline/virtual/test_pattern_generator.h\n+++ b/src/libcamera/pipeline/virtual/test_pattern_generator.h\n@@ -29,10 +29,6 @@ public:\n protected:\n \t/* Buffer of test pattern template */\n \tstd::unique_ptr<uint8_t[]> template_;\n-\n-private:\n-\t/* Shift the buffer by 1 pixel left each frame */\n-\tvoid shiftLeft(const Size &size);\n };\n \n class ColorBarsGenerator : public TestPatternGenerator\n",
    "prefixes": [
        "v1",
        "3/3"
    ]
}