Show a patch.

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

{
    "id": 14404,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/14404/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/14404/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/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": "<20211028111520.256612-10-jacopo@jmondi.org>",
    "date": "2021-10-28T11:15:19",
    "name": "[libcamera-devel,09/10] libcamera: pipeline_handler: Handle fences",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "f1d11f4ae50e79a52f7b1854d938007ef606bf16",
    "submitter": {
        "id": 3,
        "url": "https://patchwork.libcamera.org/api/1.1/people/3/?format=api",
        "name": "Jacopo Mondi",
        "email": "jacopo@jmondi.org"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/14404/mbox/",
    "series": [
        {
            "id": 2674,
            "url": "https://patchwork.libcamera.org/api/1.1/series/2674/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=2674",
            "date": "2021-10-28T11:15:10",
            "name": "libcamera: Introduce Fence support",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/2674/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/14404/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/14404/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 1B78AC324F\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 28 Oct 2021 11:14:51 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B9AB660128;\n\tThu, 28 Oct 2021 13:14:50 +0200 (CEST)",
            "from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net\n\t[217.70.183.199])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 964DA60325\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 28 Oct 2021 13:14:42 +0200 (CEST)",
            "(Authenticated sender: jacopo@jmondi.org)\n\tby relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 21D27FF802;\n\tThu, 28 Oct 2021 11:14:41 +0000 (UTC)"
        ],
        "From": "Jacopo Mondi <jacopo@jmondi.org>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Thu, 28 Oct 2021 13:15:19 +0200",
        "Message-Id": "<20211028111520.256612-10-jacopo@jmondi.org>",
        "X-Mailer": "git-send-email 2.33.1",
        "In-Reply-To": "<20211028111520.256612-1-jacopo@jmondi.org>",
        "References": "<20211028111520.256612-1-jacopo@jmondi.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH 09/10] libcamera: pipeline_handler: Handle\n\tfences",
        "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": "Before queueing a request to the device, any synchronization fence from\nthe Request framebuffers has to be waited on.\n\nStart by moving the fences to the Request, in order to reset the ones\nin the FrameBuffers and then enable all of them one by one.\n\nWhen a fence completes, make sure all fences in the Request have been\nwaited on or have expired and only after that actually queue the Request\nto the device.\n\nIf any fence in the Request has expired cancel the request and do not\nqueue it to the device.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n include/libcamera/internal/pipeline_handler.h |  2 +\n src/libcamera/pipeline_handler.cpp            | 78 ++++++++++++++++++-\n 2 files changed, 77 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h\nindex 5c3c0bc5a8b3..5b98011ac4f6 100644\n--- a/include/libcamera/internal/pipeline_handler.h\n+++ b/include/libcamera/internal/pipeline_handler.h\n@@ -29,6 +29,7 @@ class CameraConfiguration;\n class CameraManager;\n class DeviceEnumerator;\n class DeviceMatch;\n+class Fence;\n class FrameBuffer;\n class MediaDevice;\n class PipelineHandler;\n@@ -79,6 +80,7 @@ private:\n \tvoid mediaDeviceDisconnected(MediaDevice *media);\n \tvirtual void disconnect();\n \n+\tvoid fenceCompleted(Request *request, FrameBuffer *buffer, Fence *fence);\n \tvoid doQueueRequest();\n \n \tstd::vector<std::shared_ptr<MediaDevice>> mediaDevices_;\ndiff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\nindex 0f9fec1b618f..39cb680e5386 100644\n--- a/src/libcamera/pipeline_handler.cpp\n+++ b/src/libcamera/pipeline_handler.cpp\n@@ -18,6 +18,7 @@\n #include <libcamera/framebuffer.h>\n \n #include \"libcamera/internal/camera.h\"\n+#include \"libcamera/internal/framebuffer.h\"\n #include \"libcamera/internal/device_enumerator.h\"\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/request.h\"\n@@ -336,11 +337,70 @@ void PipelineHandler::queueRequest(Request *request)\n {\n \tLIBCAMERA_TRACEPOINT(request_queue, request);\n \n+\tRequest::Private *data = request->_d();\n+\n \t{\n \t\tMutexLocker lock(waitingRequestsMutex_);\n \t\twaitingRequests_.push_back(request);\n \t}\n \n+\tfor (FrameBuffer *buffer : request->pending_) {\n+\t\tif (buffer->fence() == -1)\n+\t\t\tcontinue;\n+\n+\t\t/*\n+\t\t * Move the Fence into the Request::Private list of\n+\t\t * fences. This resets the file descriptor fence in the\n+\t\t * FrameBuffer to -1.\n+\t\t */\n+\t\tdata->addFence(std::move(buffer->_d()->fence()));\n+\n+\t\tFence *fence = &data->fences().back();\n+\t\tfence->complete.connect(this,\n+\t\t\t\t\t[this, request, buffer, fence]() {\n+\t\t\t\t\t\tfenceCompleted(request, buffer, fence);\n+\t\t\t\t\t});\n+\t}\n+\n+\t/* If no fences to wait on, we can queue the request immediately. */\n+\tif (!data->pendingFences()) {\n+\t\tdoQueueRequest();\n+\n+\t\treturn;\n+\t}\n+\n+\t/*\n+\t * Now that we have added all fences, enable them one by one.\n+\t * Enabling fences while adding them to the Request would race on the\n+\t * number of pending fences.\n+\t */\n+\tfor (Fence &fence : data->fences())\n+\t\tfence.enable();\n+}\n+\n+void PipelineHandler::fenceCompleted(Request *request, FrameBuffer *buffer,\n+\t\t\t\t     Fence *fence)\n+{\n+\tRequest::Private *data = request->_d();\n+\n+\tif (fence->expired()) {\n+\t\t/*\n+\t\t * Move the fence back to the framebuffer, so that it doesn't\n+\t\t * get closed and the file descriptor number is made\n+\t\t * available again to applications.\n+\t\t */\n+\t\tFrameBuffer::Private *bufferData = buffer->_d();\n+\t\tbufferData->fence() = std::move(*fence);\n+\n+\t\tdata->fenceExpired();\n+\t} else {\n+\t\tdata->fenceCompleted();\n+\t}\n+\n+\tif (data->pendingFences())\n+\t\treturn;\n+\n+\tdata->clearFences();\n \tdoQueueRequest();\n }\n \n@@ -357,23 +417,35 @@ void PipelineHandler::doQueueRequest()\n \t\t\treturn;\n \n \t\trequest = waitingRequests_.front();\n+\t\tif (request->_d()->pendingFences())\n+\t\t\treturn;\n+\n \t\twaitingRequests_.pop_front();\n \t}\n \n-\t/* Queue Request to the pipeline handler. */\n \tCamera *camera = request->_d()->camera();\n \tCamera::Private *camData = camera->_d();\n \n \trequest->sequence_ = camData->requestSequence_++;\n-\tcamData->queuedRequests_.push_back(request);\n \n+\t/* Cancel the request if one of the fences has failed. */\n+\tif (request->_d()->expiredFences()) {\n+\t\trequest->cancel();\n+\t\tcompleteRequest(request);\n+\n+\t\tdoQueueRequest();\n+\n+\t\treturn;\n+\t}\n+\n+\t/* Queue Request to the pipeline handler. */\n+\tcamData->queuedRequests_.push_back(request);\n \tint ret = queueRequestDevice(camera, request);\n \tif (ret) {\n \t\trequest->cancel();\n \t\tcompleteRequest(request);\n \t}\n \n-\t/* Try to queue the next Request in the queue, if ready. */\n \tdoQueueRequest();\n }\n \n",
    "prefixes": [
        "libcamera-devel",
        "09/10"
    ]
}