summaryrefslogtreecommitdiff
path: root/src/qcam/main_window.cpp
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-12-12 05:22:31 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-12-14 15:35:03 +0200
commitbd4894d2596168b3435fb93b9e53dad84b2dcc7e (patch)
treef17e9bdd1f2a5e61979c1084a514a021c86a33a2 /src/qcam/main_window.cpp
parent008f2a55d141d4e5257ed83e7714d88734d67dde (diff)
android: camera_device: Replace auto with explicit type
The auto keyword facilitates writing code. It avoids typing out very long types, which can make the code more readable, but it can also have a negative impact on readability as it requires the reader (including reviewers) to look up the type of the variable. Replace one occurrence of auto with the explicit type where doing so doesn't require a long type name. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
Diffstat (limited to 'src/qcam/main_window.cpp')
0 files changed, 0 insertions, 0 deletions
3 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

import pykms
import selectors
import sys


class KMSRenderer:
    def __init__(self, state):
        self.state = state

        self.cm = state['cm']
        self.contexts = state['contexts']
        self.running = False

        card = pykms.Card()

        res = pykms.ResourceManager(card)
        conn = res.reserve_connector()
        crtc = res.reserve_crtc(conn)
        mode = conn.get_default_mode()
        modeb = mode.to_blob(card)

        req = pykms.AtomicReq(card)
        req.add_connector(conn, crtc)
        req.add_crtc(crtc, modeb)
        r = req.commit_sync(allow_modeset=True)
        assert(r == 0)

        self.card = card
        self.resman = res
        self.crtc = crtc
        self.mode = mode

        self.bufqueue = []
        self.current = None
        self.next = None
        self.cam_2_drm = {}

    # KMS

    def close(self):
        req = pykms.AtomicReq(self.card)
        for s in self.streams:
            req.add_plane(s['plane'], None, None, dst=(0, 0, 0, 0))
        req.commit()

    def add_plane(self, req, stream, fb):
        s = next(s for s in self.streams if s['stream'] == stream)
        idx = s['idx']
        plane = s['plane']

        if idx % 2 == 0:
            x = 0
        else:
            x = self.mode.hdisplay - fb.width

        if idx // 2 == 0:
            y = 0
        else:
            y = self.mode.vdisplay - fb.height

        req.add_plane(plane, fb, self.crtc, dst=(x, y, fb.width, fb.height))

    def apply_request(self, drmreq):

        buffers = drmreq['camreq'].buffers

        req = pykms.AtomicReq(self.card)

        for stream, fb in buffers.items():
            drmfb = self.cam_2_drm.get(fb, None)
            self.add_plane(req, stream, drmfb)

        req.commit()

    def handle_page_flip(self, frame, time):
        old = self.current
        self.current = self.next

        if len(self.bufqueue) > 0:
            self.next = self.bufqueue.pop(0)
        else:
            self.next = None

        if self.next:
            drmreq = self.next

            self.apply_request(drmreq)

        if old:
            req = old['camreq']
            ctx = old['camctx']
            self.state['request_prcessed'](ctx, req)

    def queue(self, drmreq):
        if not self.next:
            self.next = drmreq
            self.apply_request(drmreq)
        else:
            self.bufqueue.append(drmreq)

    # libcamera

    def setup(self):
        self.streams = []

        idx = 0
        for ctx in self.contexts:
            for stream in ctx['streams']:

                cfg = stream.configuration
                fmt = cfg.pixel_format
                fmt = pykms.PixelFormat(fmt.fourcc)

                plane = self.resman.reserve_generic_plane(self.crtc, fmt)
                assert(plane is not None)

                self.streams.append({
                    'idx': idx,
                    'stream': stream,
                    'plane': plane,
                    'fmt': fmt,
                    'size': cfg.size,
                })

                for fb in ctx['allocator'].buffers(stream):
                    w = cfg.size.width
                    h = cfg.size.height
                    fds = []
                    strides = []
                    offsets = []
                    for i in range(fb.num_planes):
                        fds.append(fb.fd(i))
                        strides.append(cfg.stride)
                        offsets.append(fb.offset(i))

                    drmfb = pykms.DmabufFramebuffer(self.card, w, h, fmt,
                                                    fds, strides, offsets)
                    self.cam_2_drm[fb] = drmfb

                idx += 1

    def readdrm(self, fileobj):
        for ev in self.card.read_events():
            if ev.type == pykms.DrmEventType.FLIP_COMPLETE:
                self.handle_page_flip(ev.seq, ev.time)

    def readcam(self, fd):
        self.running = self.state['event_handler'](self.state)

    def readkey(self, fileobj):
        sys.stdin.readline()
        self.running = False

    def run(self):
        print('Capturing...')

        self.running = True

        sel = selectors.DefaultSelector()
        sel.register(self.card.fd, selectors.EVENT_READ, self.readdrm)
        sel.register(self.cm.efd, selectors.EVENT_READ, self.readcam)
        sel.register(sys.stdin, selectors.EVENT_READ, self.readkey)

        print('Press enter to exit')

        while self.running:
            events = sel.select()
            for key, mask in events:
                callback = key.data
                callback(key.fileobj)

        print('Exiting...')

    def request_handler(self, ctx, req):

        drmreq = {
            'camctx': ctx,
            'camreq': req,
        }

        self.queue(drmreq)