Show a patch.

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

{
    "id": 2366,
    "url": "https://patchwork.libcamera.org/api/patches/2366/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/2366/",
    "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": "<20191126233620.1695316-19-niklas.soderlund@ragnatech.se>",
    "date": "2019-11-26T23:36:08",
    "name": "[libcamera-devel,18/30] libcamera: v4l2_videodevice: Add V4L2BufferCache to deal with index mapping",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "2ffeda422ae515d7b5d0696677b9f70494554a2a",
    "submitter": {
        "id": 5,
        "url": "https://patchwork.libcamera.org/api/people/5/?format=api",
        "name": "Niklas Söderlund",
        "email": "niklas.soderlund@ragnatech.se"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/2366/mbox/",
    "series": [
        {
            "id": 579,
            "url": "https://patchwork.libcamera.org/api/series/579/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=579",
            "date": "2019-11-26T23:35:50",
            "name": "libcamera: Rework buffer API",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/579/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/2366/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/2366/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<niklas.soderlund@ragnatech.se>",
        "Received": [
            "from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net\n\t[195.74.38.229])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A561C61C6F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 27 Nov 2019 00:39:38 +0100 (CET)",
            "from bismarck.berto.se (p54ac5865.dip0.t-ipconnect.de\n\t[84.172.88.101]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA\n\tid 01c2c0f2-10a6-11ea-a0b9-005056917f90;\n\tWed, 27 Nov 2019 00:39:37 +0100 (CET)"
        ],
        "X-Halon-ID": "01c2c0f2-10a6-11ea-a0b9-005056917f90",
        "Authorized-sender": "niklas@soderlund.pp.se",
        "From": "=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Wed, 27 Nov 2019 00:36:08 +0100",
        "Message-Id": "<20191126233620.1695316-19-niklas.soderlund@ragnatech.se>",
        "X-Mailer": "git-send-email 2.24.0",
        "In-Reply-To": "<20191126233620.1695316-1-niklas.soderlund@ragnatech.se>",
        "References": "<20191126233620.1695316-1-niklas.soderlund@ragnatech.se>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH 18/30] libcamera: v4l2_videodevice: Add\n\tV4L2BufferCache to deal with index mapping",
        "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>",
        "X-List-Received-Date": "Tue, 26 Nov 2019 23:39:39 -0000"
    },
    "content": "In preparation for the FrameBuffer interface add a class which will deal\nwith keeping the cache between dmafds and V4L2 video device buffer\nindexes.\n\nThis initial implement ensures that no hot association is lost while its\neviction strategy could be improved in the future.\n\nSigned-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n---\n src/libcamera/include/v4l2_videodevice.h |  20 ++++-\n src/libcamera/v4l2_videodevice.cpp       | 105 ++++++++++++++++++++++-\n 2 files changed, 123 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h\nindex 34bbff41760753bd..254f8797af42dd8a 100644\n--- a/src/libcamera/include/v4l2_videodevice.h\n+++ b/src/libcamera/include/v4l2_videodevice.h\n@@ -12,6 +12,7 @@\n \n #include <linux/videodev2.h>\n \n+#include <libcamera/buffer.h>\n #include <libcamera/geometry.h>\n #include <libcamera/pixelformats.h>\n #include <libcamera/signal.h>\n@@ -22,7 +23,6 @@\n \n namespace libcamera {\n \n-class Buffer;\n class BufferMemory;\n class BufferPool;\n class EventNotifier;\n@@ -105,6 +105,24 @@ struct V4L2Capability final : v4l2_capability {\n \t}\n };\n \n+class V4L2BufferCache\n+{\n+public:\n+\tV4L2BufferCache(unsigned int size);\n+\tV4L2BufferCache(const std::vector<FrameBuffer *> buffers);\n+\n+\tint fetch(const FrameBuffer *buffer);\n+\tvoid put(unsigned int index);\n+\n+private:\n+\tstruct CacheInfo {\n+\t\tbool free;\n+\t\tstd::vector<FrameBuffer::Plane> last;\n+\t};\n+\n+\tstd::vector<CacheInfo> cache_;\n+};\n+\n class V4L2DeviceFormat\n {\n public:\ndiff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\nindex a05dd6a1f7d86eaa..c82f2829601bd14c 100644\n--- a/src/libcamera/v4l2_videodevice.cpp\n+++ b/src/libcamera/v4l2_videodevice.cpp\n@@ -19,7 +19,6 @@\n \n #include <linux/drm_fourcc.h>\n \n-#include <libcamera/buffer.h>\n #include <libcamera/event_notifier.h>\n \n #include \"log.h\"\n@@ -134,6 +133,110 @@ LOG_DECLARE_CATEGORY(V4L2)\n  * \\return True if the video device provides Streaming I/O IOCTLs\n  */\n \n+/**\n+ * \\class V4L2BufferCache\n+ * \\brief Hot cache of associations between V4L2 index and FrameBuffer\n+ *\n+ * There is performance to be gained if the same V4L2 buffer index can be\n+ * reused for the same FrameBuffer object as the kernel don't have to redo\n+ * the mapping. The V4L2BufferCache tries to keep a hot-cache of mappings\n+ * between the two.\n+ *\n+ * If there is a cache miss is not critical, everything still works as expected.\n+ */\n+\n+/**\n+ * \\brief Create a empty cache of a given size\n+ * \\param[in] size Size of cache to create\n+ *\n+ * Create a cold cache with \\a size entries. The cache will be populated as\n+ * it's being used.\n+ */\n+V4L2BufferCache::V4L2BufferCache(unsigned int size)\n+{\n+\tcache_.resize(size, { .free = true, .last = {} });\n+}\n+\n+/**\n+ * \\brief Create a pre-populated cache\n+ * \\param[in] buffers Array of buffers to pre-populated with\n+ *\n+ * Create a warm cache from \\a buffers.\n+ */\n+V4L2BufferCache::V4L2BufferCache(const std::vector<FrameBuffer *> buffers)\n+{\n+\tfor (const FrameBuffer *buffer : buffers)\n+\t\tcache_.push_back({ .free = true, .last = buffer->planes() });\n+}\n+\n+/**\n+ * \\brief Fetch a index from the cache\n+ * \\param[in] buffer FrameBuffer to match\n+ *\n+ * Try to find \\a buffer in cache and if it's free reuse the last used index\n+ * for this buffer. If the buffer have never been seen or if have been evinced\n+ * from the cache the first free index is pieced instead. Likewise if the last\n+ * used index is in use a new free index is picked.\n+ *\n+ * When an index is picked it is marked as in-use and returned to the caller.\n+ * The association is also recorded so it if possible can reused the next time\n+ * the FrameBuffer is seen.\n+ *\n+ * \\return V4L2 buffer index\n+ */\n+int V4L2BufferCache::fetch(const FrameBuffer *buffer)\n+{\n+\tint use = -1;\n+\n+\tfor (unsigned int index = 0; index < cache_.size(); index++) {\n+\t\tif (!cache_[index].free)\n+\t\t\tcontinue;\n+\n+\t\tif (use < 0)\n+\t\t\tuse = index;\n+\n+\t\t/* Try to find a cache hit by comparing the planes. */\n+\t\tstd::vector<FrameBuffer::Plane> planes = buffer->planes();\n+\t\tif (cache_[index].last.size() != planes.size())\n+\t\t\tcontinue;\n+\n+\t\tbool match = true;\n+\t\tfor (unsigned int i = 0; i < planes.size(); i++) {\n+\t\t\tif (cache_[index].last[i].fd != planes[i].fd ||\n+\t\t\t    cache_[index].last[i].length != planes[i].length) {\n+\t\t\t\tmatch = false;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (!match)\n+\t\t\tcontinue;\n+\n+\t\tuse = index;\n+\t\tbreak;\n+\t}\n+\n+\tif (use < 0)\n+\t\treturn -ENOENT;\n+\n+\tcache_[use].free = false;\n+\tcache_[use].last = buffer->planes();\n+\n+\treturn use;\n+}\n+\n+/**\n+ * \\brief Pit a V4L2 index back in the cache\n+ * \\param[in] index V4L2 index\n+ *\n+ * Mark the \\a index as free in the cache so it can be reused.\n+ */\n+void V4L2BufferCache::put(unsigned int index)\n+{\n+\tASSERT(index < cache_.size());\n+\tcache_[index].free = true;\n+}\n+\n /**\n  * \\class V4L2DeviceFormat\n  * \\brief The V4L2 video device image format and sizes\n",
    "prefixes": [
        "libcamera-devel",
        "18/30"
    ]
}