/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2021, Ideas on Board Oy
 *
 * drm.h - DRM/KMS Helpers
 */

#pragma once

#include <array>
#include <list>
#include <map>
#include <memory>
#include <stdint.h>
#include <string>
#include <vector>

#include <libcamera/base/signal.h>
#include <libcamera/base/span.h>

#include <libdrm/drm.h>
#include <xf86drm.h>
#include <xf86drmMode.h>

namespace libcamera {
class FrameBuffer;
class PixelFormat;
class Size;
} /* namespace libcamera */

namespace DRM {

class Device;
class Plane;
class Property;
class PropertyValue;

class Object
{
public:
	enum Type {
		TypeCrtc = DRM_MODE_OBJECT_CRTC,
		TypeConnector = DRM_MODE_OBJECT_CONNECTOR,
		TypeEncoder = DRM_MODE_OBJECT_ENCODER,
		TypeMode = DRM_MODE_OBJECT_MODE,
		TypeProperty = DRM_MODE_OBJECT_PROPERTY,
		TypeFb = DRM_MODE_OBJECT_FB,
		TypeBlob = DRM_MODE_OBJECT_BLOB,
		TypePlane = DRM_MODE_OBJECT_PLANE,
		TypeAny = DRM_MODE_OBJECT_ANY,
	};

	Object(Device *dev, uint32_t id, Type type);
	virtual ~Object();

	Device *device() const { return dev_; }
	uint32_t id() const { return id_; }
	Type type() const { return type_; }

	const Property *property(const std::string &name) const;
	const PropertyValue *propertyValue(const std::string &name) const;
	const std::vector<PropertyValue> &properties() const { return properties_; }

protected:
	virtual int setup()
	{
		return 0;
	}

	uint32_t id_;

private:
	friend Device;

	Device *dev_;
	Type type_;
	std::vector<PropertyValue> properties_;
};

class Property : public Object
{
public:
	enum Type {
		TypeUnknown = 0,
		TypeRange,
		TypeEnum,
		TypeBlob,
		TypeBitmask,
		TypeObject,
		TypeSignedRange,
	};

	Property(Device *dev, drmModePropertyRes *property);

	Type type() const { return type_; }
	const std::string &name() const { return name_; }

	bool isImmutable() const { return flags_ & DRM_MODE_PROP_IMMUTABLE; }

	const std::vector<uint64_t> values() const { return values_; }
	const std::map<uint32_t, std::string> &enums() const { return enums_; }
	const std::vector<uint32_t> blobs() const { return blobs_; }

private:
	Type type_;
	std::string name_;
	uint32_t flags_;
	std::vector<uint64_t> values_;
	std::map<uint32_t, std::string> enums_;
	std::vector<uint32_t> blobs_;
};

class PropertyValue
{
public:
	PropertyValue(uint32_t id, uint64_t value)
		: id_(id), value_(value)
	{
	}

	uint32_t id() const { return id_; }
	uint32_t value() const { return value_; }

private:
	uint32_t id_;
	uint64_t value_;
};

class Blob : public Object
{
public:
	Blob(Device *dev, const libcamera::Span<const uint8_t> &data);
	~Blob();

	bool isValid() const { return id() != 0; }
};

class Mode : public drmModeModeInfo
{
public:
	Mode(const drmModeModeInfo &mode);

	std::unique_ptr<Blob> toBlob(Device *dev) const;
};

class Crtc : public Object
{
public:
	Crtc(Device *dev, const drmModeCrtc *crtc, unsigned int index);

	unsigned int index() const { return index_; }
	const std::vector<const Plane *> &planes() const { return planes_; }

private:
	friend Device;

	unsigned int index_;
	std::vector<const Plane *> planes_;
};

class Encoder : public Object
{
public:
	Encoder(Device *dev, const drmModeEncoder *encoder);

	uint32_t type() const { return type_; }

	const std::vector<const Crtc *> &possibleCrtcs() const { return possibleCrtcs_; }

private:
	uint32_t type_;
	std::vector<const Crtc *> possibleCrtcs_;
};

class Connector : public Object
{
public:
	enum Status {
		Connected,
		Disconnected,
		Unknown,
	};

	Connector(Device *dev, const drmModeConnector *connector);

	uint32_t type() const { return type_; }
	const std::string &name() const { return name_; }

	Status status() const { return status_; }

	const std::vector<const Encoder *> &encoders() const { return encoders_; }
	const std::vector<Mode> &modes() const { return modes_; }

private:
	uint32_t type_;
	std::string name_;
	Status status_;
	std::vector<const Encoder *> encoders_;
	std::vector<Mode> modes_;
};

class Plane : public Object
{
public:
	enum Type {
		TypeOverlay,
		TypePrimary,
		TypeCursor,
	};

	Plane(Device *dev, const drmModePlane *plane);

	Type type() const { return type_; }
	const std::vector<uint32_t> &formats() const { return formats_; }
	const std::vector<const Crtc *> &possibleCrtcs() const { return possibleCrtcs_; }

	bool supportsFormat(const libcamera::PixelFormat &format) const;

protected:
	int setup() override;

private:
	friend class Device;

	Type type_;
	std::vector<uint32_t> formats_;
	std::vector<const Crtc *> possibleCrtcs_;
	uint32_t possibleCrtcsMask_;
};

class FrameBuffer : public Object
{
public:
	struct Plane {
		uint32_t handle;
	};

	~FrameBuffer();

private:
	friend class Device;

	FrameBuffer(Device *dev);

	std::map<int, Plane> planes_;
};

class AtomicRequest
{
public:
	enum Flags {
		FlagAllowModeset = (1 << 0),
		FlagAsync = (1 << 1),
		FlagTestOnly = (1 << 2),
	};

	AtomicRequest(Device *dev);
	~AtomicRequest();

	Device *device() const { return dev_; }
	bool isValid() const { return valid_; }

	int addProperty(const Object *object, const std::string &property,
			uint64_t value);
	int addProperty(const Object *object, const std::string &property,
			std::unique_ptr<Blob> blob);
	int commit(unsigned int flags = 0);

private:
	AtomicRequest(const AtomicRequest &) = delete;
	AtomicRequest(const AtomicRequest &&) = delete;
	AtomicRequest &operator=(const AtomicRequest &) = delete;
	AtomicRequest &operator=(const AtomicRequest &&) = delete;

	int addProperty(uint32_t object, uint32_t property, uint64_t value);

	Device *dev_;
	bool valid_;
	drmModeAtomicReq *request_;
	std::list<std::unique_ptr<Blob>> blobs_;
};

class Device
{
public:
	Device();
	~Device();

	int init();

	int fd() const { return fd_; }

	const std::list<Crtc> &crtcs() const { return crtcs_; }
	const std::list<Encoder> &encoders() const { return encoders_; }
	const std::list<Connector> &connectors() const { return connectors_; }
	const std::list<Plane> &planes() const { return planes_; }
	const std::list<Property> &properties() const { return properties_; }

	const Object *object(uint32_t id);

	std::unique_ptr<FrameBuffer> createFrameBuffer(
		const libcamera::FrameBuffer &buffer,
		const libcamera::PixelFormat &format,
		const libcamera::Size &size,
		const std::array<uint32_t, 4> &strides);

	libcamera::Signal<AtomicRequest *> requestComplete;

private:
	Device(const Device &) = delete;
	Device(const Device &&) = delete;
	Device &operator=(const Device &) = delete;
	Device &operator=(const Device &&) = delete;

	int openCard();
	int getResources();

	void drmEvent();
	static void pageFlipComplete(int fd, unsigned int sequence,
				     unsigned int tv_sec, unsigned int tv_usec,
				     void *user_data);

	int fd_;

	std::list<Crtc> crtcs_;
	std::list<Encoder> encoders_;
	std::list<Connector> connectors_;
	std::list<Plane> planes_;
	std::list<Property> properties_;

	std::map<uint32_t, Object *> objects_;
};

} /* namespace DRM */
>128</a>
<a id='n129' href='#n129'>129</a>
<a id='n130' href='#n130'>130</a>
<a id='n131' href='#n131'>131</a>
<a id='n132' href='#n132'>132</a>
<a id='n133' href='#n133'>133</a>
<a id='n134' href='#n134'>134</a>
<a id='n135' href='#n135'>135</a>
<a id='n136' href='#n136'>136</a>
<a id='n137' href='#n137'>137</a>
<a id='n138' href='#n138'>138</a>
<a id='n139' href='#n139'>139</a>
<a id='n140' href='#n140'>140</a>
<a id='n141' href='#n141'>141</a>
<a id='n142' href='#n142'>142</a>
<a id='n143' href='#n143'>143</a>
<a id='n144' href='#n144'>144</a>
<a id='n145' href='#n145'>145</a>
<a id='n146' href='#n146'>146</a>
<a id='n147' href='#n147'>147</a>
<a id='n148' href='#n148'>148</a>
<a id='n149' href='#n149'>149</a>
<a id='n150' href='#n150'>150</a>
<a id='n151' href='#n151'>151</a>
<a id='n152' href='#n152'>152</a>
<a id='n153' href='#n153'>153</a>
<a id='n154' href='#n154'>154</a>
<a id='n155' href='#n155'>155</a>
<a id='n156' href='#n156'>156</a>
<a id='n157' href='#n157'>157</a>
<a id='n158' href='#n158'>158</a>
<a id='n159' href='#n159'>159</a>
<a id='n160' href='#n160'>160</a>
<a id='n161' href='#n161'>161</a>
<a id='n162' href='#n162'>162</a>
<a id='n163' href='#n163'>163</a>
<a id='n164' href='#n164'>164</a>
<a id='n165' href='#n165'>165</a>
<a id='n166' href='#n166'>166</a>
<a id='n167' href='#n167'>167</a>
<a id='n168' href='#n168'>168</a>
<a id='n169' href='#n169'>169</a>
<a id='n170' href='#n170'>170</a>
<a id='n171' href='#n171'>171</a>
<a id='n172' href='#n172'>172</a>
<a id='n173' href='#n173'>173</a>
<a id='n174' href='#n174'>174</a>
<a id='n175' href='#n175'>175</a>
<a id='n176' href='#n176'>176</a>
<a id='n177' href='#n177'>177</a>
<a id='n178' href='#n178'>178</a>
<a id='n179' href='#n179'>179</a>
<a id='n180' href='#n180'>180</a>
<a id='n181' href='#n181'>181</a>
<a id='n182' href='#n182'>182</a>
<a id='n183' href='#n183'>183</a>
<a id='n184' href='#n184'>184</a>
<a id='n185' href='#n185'>185</a>
<a id='n186' href='#n186'>186</a>
<a id='n187' href='#n187'>187</a>
<a id='n188' href='#n188'>188</a>
<a id='n189' href='#n189'>189</a>
<a id='n190' href='#n190'>190</a>
<a id='n191' href='#n191'>191</a>
<a id='n192' href='#n192'>192</a>
<a id='n193' href='#n193'>193</a>
<a id='n194' href='#n194'>194</a>
<a id='n195' href='#n195'>195</a>
<a id='n196' href='#n196'>196</a>
<a id='n197' href='#n197'>197</a>
<a id='n198' href='#n198'>198</a>
<a id='n199' href='#n199'>199</a>
<a id='n200' href='#n200'>200</a>
<a id='n201' href='#n201'>201</a>
<a id='n202' href='#n202'>202</a>
<a id='n203' href='#n203'>203</a>
<a id='n204' href='#n204'>204</a>
<a id='n205' href='#n205'>205</a>
<a id='n206' href='#n206'>206</a>
<a id='n207' href='#n207'>207</a>
<a id='n208' href='#n208'>208</a>
<a id='n209' href='#n209'>209</a>
<a id='n210' href='#n210'>210</a>
<a id='n211' href='#n211'>211</a>
<a id='n212' href='#n212'>212</a>
<a id='n213' href='#n213'>213</a>
<a id='n214' href='#n214'>214</a>
<a id='n215' href='#n215'>215</a>
<a id='n216' href='#n216'>216</a>
<a id='n217' href='#n217'>217</a>
<a id='n218' href='#n218'>218</a>
<a id='n219' href='#n219'>219</a>
<a id='n220' href='#n220'>220</a>
<a id='n221' href='#n221'>221</a>
<a id='n222' href='#n222'>222</a>
<a id='n223' href='#n223'>223</a>
<a id='n224' href='#n224'>224</a>
<a id='n225' href='#n225'>225</a>
<a id='n226' href='#n226'>226</a>
<a id='n227' href='#n227'>227</a>
<a id='n228' href='#n228'>228</a>
<a id='n229' href='#n229'>229</a>
<a id='n230' href='#n230'>230</a>
<a id='n231' href='#n231'>231</a>
<a id='n232' href='#n232'>232</a>
<a id='n233' href='#n233'>233</a>
<a id='n234' href='#n234'>234</a>
<a id='n235' href='#n235'>235</a>
<a id='n236' href='#n236'>236</a>
<a id='n237' href='#n237'>237</a>
<a id='n238' href='#n238'>238</a>
<a id='n239' href='#n239'>239</a>
<a id='n240' href='#n240'>240</a>
<a id='n241' href='#n241'>241</a>
<a id='n242' href='#n242'>242</a>
<a id='n243' href='#n243'>243</a>
<a id='n244' href='#n244'>244</a>
<a id='n245' href='#n245'>245</a>
<a id='n246' href='#n246'>246</a>
<a id='n247' href='#n247'>247</a>
<a id='n248' href='#n248'>248</a>
<a id='n249' href='#n249'>249</a>
<a id='n250' href='#n250'>250</a>
<a id='n251' href='#n251'>251</a>
<a id='n252' href='#n252'>252</a>
<a id='n253' href='#n253'>253</a>
<a id='n254' href='#n254'>254</a>
<a id='n255' href='#n255'>255</a>
<a id='n256' href='#n256'>256</a>
<a id='n257' href='#n257'>257</a>
<a id='n258' href='#n258'>258</a>
<a id='n259' href='#n259'>259</a>
<a id='n260' href='#n260'>260</a>
<a id='n261' href='#n261'>261</a>
<a id='n262' href='#n262'>262</a>
<a id='n263' href='#n263'>263</a>
<a id='n264' href='#n264'>264</a>
<a id='n265' href='#n265'>265</a>
<a id='n266' href='#n266'>266</a>
<a id='n267' href='#n267'>267</a>
<a id='n268' href='#n268'>268</a>
<a id='n269' href='#n269'>269</a>
<a id='n270' href='#n270'>270</a>
<a id='n271' href='#n271'>271</a>
<a id='n272' href='#n272'>272</a>
<a id='n273' href='#n273'>273</a>
<a id='n274' href='#n274'>274</a>
<a id='n275' href='#n275'>275</a>
<a id='n276' href='#n276'>276</a>
<a id='n277' href='#n277'>277</a>
<a id='n278' href='#n278'>278</a>
<a id='n279' href='#n279'>279</a>
<a id='n280' href='#n280'>280</a>
<a id='n281' href='#n281'>281</a>
<a id='n282' href='#n282'>282</a>
<a id='n283' href='#n283'>283</a>
<a id='n284' href='#n284'>284</a>
<a id='n285' href='#n285'>285</a>
<a id='n286' href='#n286'>286</a>
<a id='n287' href='#n287'>287</a>
<a id='n288' href='#n288'>288</a>
<a id='n289' href='#n289'>289</a>
<a id='n290' href='#n290'>290</a>
<a id='n291' href='#n291'>291</a>
<a id='n292' href='#n292'>292</a>
<a id='n293' href='#n293'>293</a>
<a id='n294' href='#n294'>294</a>
<a id='n295' href='#n295'>295</a>
<a id='n296' href='#n296'>296</a>
<a id='n297' href='#n297'>297</a>
<a id='n298' href='#n298'>298</a>
<a id='n299' href='#n299'>299</a>
<a id='n300' href='#n300'>300</a>
<a id='n301' href='#n301'>301</a>
<a id='n302' href='#n302'>302</a>
<a id='n303' href='#n303'>303</a>
<a id='n304' href='#n304'>304</a>
<a id='n305' href='#n305'>305</a>
<a id='n306' href='#n306'>306</a>
<a id='n307' href='#n307'>307</a>
<a id='n308' href='#n308'>308</a>
<a id='n309' href='#n309'>309</a>
<a id='n310' href='#n310'>310</a>
<a id='n311' href='#n311'>311</a>
<a id='n312' href='#n312'>312</a>
<a id='n313' href='#n313'>313</a>
<a id='n314' href='#n314'>314</a>
<a id='n315' href='#n315'>315</a>
<a id='n316' href='#n316'>316</a>
<a id='n317' href='#n317'>317</a>
<a id='n318' href='#n318'>318</a>
<a id='n319' href='#n319'>319</a>
<a id='n320' href='#n320'>320</a>
<a id='n321' href='#n321'>321</a>
<a id='n322' href='#n322'>322</a>
<a id='n323' href='#n323'>323</a>
<a id='n324' href='#n324'>324</a>
<a id='n325' href='#n325'>325</a>
<a id='n326' href='#n326'>326</a>
<a id='n327' href='#n327'>327</a>
<a id='n328' href='#n328'>328</a>
<a id='n329' href='#n329'>329</a>
<a id='n330' href='#n330'>330</a>
<a id='n331' href='#n331'>331</a>
<a id='n332' href='#n332'>332</a>
<a id='n333' href='#n333'>333</a>
<a id='n334' href='#n334'>334</a>
<a id='n335' href='#n335'>335</a>
<a id='n336' href='#n336'>336</a>
<a id='n337' href='#n337'>337</a>
<a id='n338' href='#n338'>338</a>
<a id='n339' href='#n339'>339</a>
<a id='n340' href='#n340'>340</a>
<a id='n341' href='#n341'>341</a>
<a id='n342' href='#n342'>342</a>
</pre></td>
<td class='lines'><pre><code><span class="hl com">/* SPDX-License-Identifier: GPL-2.0-or-later */</span>
<span class="hl com">/*</span>
<span class="hl com"> * Copyright (C) 2021, Google Inc.</span>
<span class="hl com"> *</span>
<span class="hl com"> * fence.cpp - Fence test</span>
<span class="hl com"> */</span>

<span class="hl ppc">#include &lt;iostream&gt;</span>
<span class="hl ppc">#include &lt;memory&gt;</span>
<span class="hl ppc">#include &lt;sys/eventfd.h&gt;</span>
<span class="hl ppc">#include &lt;unistd.h&gt;</span>

<span class="hl ppc">#include &lt;libcamera/base/event_dispatcher.h&gt;</span>
<span class="hl ppc">#include &lt;libcamera/base/thread.h&gt;</span>
<span class="hl ppc">#include &lt;libcamera/base/timer.h&gt;</span>
<span class="hl ppc">#include &lt;libcamera/base/unique_fd.h&gt;</span>
<span class="hl ppc">#include &lt;libcamera/base/utils.h&gt;</span>

<span class="hl ppc">#include &lt;libcamera/fence.h&gt;</span>
<span class="hl ppc">#include &lt;libcamera/framebuffer_allocator.h&gt;</span>

<span class="hl ppc">#include</span> <span class="hl pps">&quot;camera_test.h&quot;</span><span class="hl ppc"></span>
<span class="hl ppc">#include</span> <span class="hl pps">&quot;test.h&quot;</span><span class="hl ppc"></span>

<span class="hl kwa">using namespace</span> libcamera<span class="hl opt">;</span>
<span class="hl kwa">using namespace</span> std<span class="hl opt">;</span>
<span class="hl kwa">using namespace</span> <span class="hl kwc">std</span><span class="hl opt">::</span>chrono_literals<span class="hl opt">;</span>

<span class="hl kwc">class</span> FenceTest <span class="hl opt">:</span> <span class="hl kwc">public</span> CameraTest<span class="hl opt">,</span> <span class="hl kwc">public</span> Test
<span class="hl opt">{</span>
<span class="hl kwc">public</span><span class="hl opt">:</span>
	<span class="hl kwd">FenceTest</span><span class="hl opt">();</span>

<span class="hl kwc">protected</span><span class="hl opt">:</span>
	<span class="hl kwb">int</span> <span class="hl kwd">init</span><span class="hl opt">()</span> override<span class="hl opt">;</span>
	<span class="hl kwb">int</span> <span class="hl kwd">run</span><span class="hl opt">()</span> override<span class="hl opt">;</span>

<span class="hl kwc">private</span><span class="hl opt">:</span>
	<span class="hl kwb">int</span> <span class="hl kwd">validateExpiredRequest</span><span class="hl opt">(</span>Request <span class="hl opt">*</span>request<span class="hl opt">);</span>
	<span class="hl kwb">int</span> <span class="hl kwd">validateRequest</span><span class="hl opt">(</span>Request <span class="hl opt">*</span>request<span class="hl opt">);</span>
	<span class="hl kwb">void</span> <span class="hl kwd">requestComplete</span><span class="hl opt">(</span>Request <span class="hl opt">*</span>request<span class="hl opt">);</span>
	<span class="hl kwb">void</span> <span class="hl kwd">requestRequeue</span><span class="hl opt">(</span>Request <span class="hl opt">*</span>request<span class="hl opt">);</span>

	<span class="hl kwb">void</span> <span class="hl kwd">signalFence</span><span class="hl opt">();</span>

	<span class="hl kwc">std</span><span class="hl opt">::</span>unique_ptr<span class="hl opt">&lt;</span>Fence<span class="hl opt">&gt;</span> fence_<span class="hl opt">;</span>
	EventDispatcher <span class="hl opt">*</span>dispatcher_<span class="hl opt">;</span>
	UniqueFD eventFd_<span class="hl opt">;</span>
	UniqueFD eventFd2_<span class="hl opt">;</span>
	Timer fenceTimer_<span class="hl opt">;</span>

	<span class="hl kwc">std</span><span class="hl opt">::</span>vector<span class="hl opt">&lt;</span><span class="hl kwc">std</span><span class="hl opt">::</span>unique_ptr<span class="hl opt">&lt;</span>Request<span class="hl opt">&gt;&gt;</span> requests_<span class="hl opt">;</span>
	<span class="hl kwc">std</span><span class="hl opt">::</span>unique_ptr<span class="hl opt">&lt;</span>CameraConfiguration<span class="hl opt">&gt;</span> config_<span class="hl opt">;</span>
	<span class="hl kwc">std</span><span class="hl opt">::</span>unique_ptr<span class="hl opt">&lt;</span>FrameBufferAllocator<span class="hl opt">&gt;</span> allocator_<span class="hl opt">;</span>

	Stream <span class="hl opt">*</span>stream_<span class="hl opt">;</span>

	<span class="hl kwb">bool</span> expectedCompletionResult_ <span class="hl opt">=</span> <span class="hl kwa">true</span><span class="hl opt">;</span>
	<span class="hl kwb">bool</span> setFence_ <span class="hl opt">=</span> <span class="hl kwa">true</span><span class="hl opt">;</span>

	<span class="hl kwb">unsigned int</span> completedRequest_<span class="hl opt">;</span>

	<span class="hl kwb">unsigned int</span> signalledRequestId_<span class="hl opt">;</span>
	<span class="hl kwb">unsigned int</span> expiredRequestId_<span class="hl opt">;</span>
	<span class="hl kwb">unsigned int</span> nbuffers_<span class="hl opt">;</span>

	<span class="hl kwb">int</span> efd2_<span class="hl opt">;</span>
	<span class="hl kwb">int</span> efd_<span class="hl opt">;</span>
<span class="hl opt">};</span>

<span class="hl kwc">FenceTest</span><span class="hl opt">::</span><span class="hl kwd">FenceTest</span><span class="hl opt">()</span>
	<span class="hl opt">:</span> <span class="hl kwd">CameraTest</span><span class="hl opt">(</span><span class="hl str">&quot;platform/vimc.0 Sensor B&quot;</span><span class="hl opt">)</span>
<span class="hl opt">{</span>
<span class="hl opt">}</span>

<span class="hl kwb">int</span> <span class="hl kwc">FenceTest</span><span class="hl opt">::</span><span class="hl kwd">init</span><span class="hl opt">()</span>
<span class="hl opt">{</span>
	<span class="hl com">/* Make sure the CameraTest constructor succeeded. */</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span>status_ <span class="hl opt">!=</span> TestPass<span class="hl opt">)</span>
		<span class="hl kwa">return</span> status_<span class="hl opt">;</span>

	dispatcher_ <span class="hl opt">=</span> <span class="hl kwc">Thread</span><span class="hl opt">::</span><span class="hl kwd">current</span><span class="hl opt">()-&gt;</span><span class="hl kwd">eventDispatcher</span><span class="hl opt">();</span>

	<span class="hl com">/*</span>
<span class="hl com">	 * Create two eventfds to model the fences. This is enough to support the</span>
<span class="hl com">	 * needs of libcamera which only needs to wait for read events through</span>
<span class="hl com">	 * poll(). Once native support for fences will be available in the</span>
<span class="hl com">	 * backend kernel APIs this will need to be replaced by a sw_sync fence,</span>
<span class="hl com">	 * but that requires debugfs.</span>
<span class="hl com">	 */</span>
	eventFd_ <span class="hl opt">=</span> <span class="hl kwd">UniqueFD</span><span class="hl opt">(</span><span class="hl kwd">eventfd</span><span class="hl opt">(</span><span class="hl num">0</span><span class="hl opt">,</span> EFD_CLOEXEC <span class="hl opt">|</span> EFD_NONBLOCK<span class="hl opt">));</span>
	eventFd2_ <span class="hl opt">=</span> <span class="hl kwd">UniqueFD</span><span class="hl opt">(</span><span class="hl kwd">eventfd</span><span class="hl opt">(</span><span class="hl num">0</span><span class="hl opt">,</span> EFD_CLOEXEC <span class="hl opt">|</span> EFD_NONBLOCK<span class="hl opt">));</span>
	<span class="hl kwa">if</span> <span class="hl opt">(!</span>eventFd_<span class="hl opt">.</span><span class="hl kwd">isValid</span><span class="hl opt">() || !</span>eventFd2_<span class="hl opt">.</span><span class="hl kwd">isValid</span><span class="hl opt">()) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Unable to create eventfd&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	efd_ <span class="hl opt">=</span> eventFd_<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">();</span>
	efd2_ <span class="hl opt">=</span> eventFd2_<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">();</span>

	config_ <span class="hl opt">=</span> camera_<span class="hl opt">-&gt;</span><span class="hl kwd">generateConfiguration</span><span class="hl opt">({</span> <span class="hl kwc">StreamRole</span><span class="hl opt">::</span>Viewfinder <span class="hl opt">});</span>
	<span class="hl kwa">if</span> <span class="hl opt">(!</span>config_ <span class="hl opt">||</span> config_<span class="hl opt">-&gt;</span><span class="hl kwd">size</span><span class="hl opt">() !=</span> <span class="hl num">1</span><span class="hl opt">) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Failed to generate default configuration&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl kwa">if</span> <span class="hl opt">(</span>camera_<span class="hl opt">-&gt;</span><span class="hl kwd">acquire</span><span class="hl opt">()) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Failed to acquire the camera&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl kwa">if</span> <span class="hl opt">(</span>camera_<span class="hl opt">-&gt;</span><span class="hl kwd">configure</span><span class="hl opt">(</span>config_<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">())) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Failed to set default configuration&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	StreamConfiguration <span class="hl opt">&amp;</span>cfg <span class="hl opt">=</span> config_<span class="hl opt">-&gt;</span><span class="hl kwd">at</span><span class="hl opt">(</span><span class="hl num">0</span><span class="hl opt">);</span>
	stream_ <span class="hl opt">=</span> cfg<span class="hl opt">.</span><span class="hl kwd">stream</span><span class="hl opt">();</span>

	allocator_ <span class="hl opt">=</span> <span class="hl kwc">std</span><span class="hl opt">::</span>make_unique<span class="hl opt">&lt;</span>FrameBufferAllocator<span class="hl opt">&gt;(</span>camera_<span class="hl opt">);</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span>allocator_<span class="hl opt">-&gt;</span><span class="hl kwd">allocate</span><span class="hl opt">(</span>stream_<span class="hl opt">) &lt;</span> <span class="hl num">0</span><span class="hl opt">)</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>

	nbuffers_ <span class="hl opt">=</span> allocator_<span class="hl opt">-&gt;</span><span class="hl kwd">buffers</span><span class="hl opt">(</span>stream_<span class="hl opt">).</span><span class="hl kwd">size</span><span class="hl opt">();</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span>nbuffers_ <span class="hl opt">&lt;</span> <span class="hl num">2</span><span class="hl opt">) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Not enough buffers available&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	signalledRequestId_ <span class="hl opt">=</span> nbuffers_ <span class="hl opt">-</span> <span class="hl num">2</span><span class="hl opt">;</span>
	expiredRequestId_ <span class="hl opt">=</span> nbuffers_ <span class="hl opt">-</span> <span class="hl num">1</span><span class="hl opt">;</span>

	<span class="hl kwa">return</span> TestPass<span class="hl opt">;</span>
<span class="hl opt">}</span>

<span class="hl kwb">int</span> <span class="hl kwc">FenceTest</span><span class="hl opt">::</span><span class="hl kwd">validateExpiredRequest</span><span class="hl opt">(</span>Request <span class="hl opt">*</span>request<span class="hl opt">)</span>
<span class="hl opt">{</span>
	<span class="hl com">/* The last request is expected to fail. */</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span>request<span class="hl opt">-&gt;</span><span class="hl kwd">status</span><span class="hl opt">() !=</span> <span class="hl kwc">Request</span><span class="hl opt">::</span>RequestCancelled<span class="hl opt">) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;The last request should have failed: &quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	FrameBuffer <span class="hl opt">*</span>buffer <span class="hl opt">=</span> request<span class="hl opt">-&gt;</span><span class="hl kwd">buffers</span><span class="hl opt">().</span><span class="hl kwd">begin</span><span class="hl opt">()-&gt;</span>second<span class="hl opt">;</span>
	<span class="hl kwc">std</span><span class="hl opt">::</span>unique_ptr<span class="hl opt">&lt;</span>Fence<span class="hl opt">&gt;</span> fence <span class="hl opt">=</span> buffer<span class="hl opt">-&gt;</span><span class="hl kwd">releaseFence</span><span class="hl opt">();</span>
	<span class="hl kwa">if</span> <span class="hl opt">(!</span>fence<span class="hl opt">) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;The expired fence should be present&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl kwa">if</span> <span class="hl opt">(!</span>fence<span class="hl opt">-&gt;</span><span class="hl kwd">isValid</span><span class="hl opt">()) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;The expired fence should be valid&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	UniqueFD fd <span class="hl opt">=</span> fence<span class="hl opt">-&gt;</span><span class="hl kwd">release</span><span class="hl opt">();</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span>fd<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">() !=</span> efd_<span class="hl opt">) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;The expired fence file descriptor should not change&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl kwa">return</span> TestPass<span class="hl opt">;</span>
<span class="hl opt">}</span>

<span class="hl kwb">int</span> <span class="hl kwc">FenceTest</span><span class="hl opt">::</span><span class="hl kwd">validateRequest</span><span class="hl opt">(</span>Request <span class="hl opt">*</span>request<span class="hl opt">)</span>
<span class="hl opt">{</span>
	<span class="hl kwb">uint64_t</span> cookie <span class="hl opt">=</span> request<span class="hl opt">-&gt;</span><span class="hl kwd">cookie</span><span class="hl opt">();</span>

	<span class="hl com">/* All requests but the last are expected to succeed. */</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span>request<span class="hl opt">-&gt;</span><span class="hl kwd">status</span><span class="hl opt">() !=</span> <span class="hl kwc">Request</span><span class="hl opt">::</span>RequestComplete<span class="hl opt">) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Unexpected request failure: &quot;</span> <span class="hl opt">&lt;&lt;</span> cookie <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl com">/* A successfully completed request should have the Fence closed. */</span>
	<span class="hl kwb">const</span> <span class="hl kwc">Request</span><span class="hl opt">::</span>BufferMap <span class="hl opt">&amp;</span>buffers <span class="hl opt">=</span> request<span class="hl opt">-&gt;</span><span class="hl kwd">buffers</span><span class="hl opt">();</span>
	FrameBuffer <span class="hl opt">*</span>buffer <span class="hl opt">=</span> buffers<span class="hl opt">.</span><span class="hl kwd">begin</span><span class="hl opt">()-&gt;</span>second<span class="hl opt">;</span>

	<span class="hl kwc">std</span><span class="hl opt">::</span>unique_ptr<span class="hl opt">&lt;</span>Fence<span class="hl opt">&gt;</span> bufferFence <span class="hl opt">=</span> buffer<span class="hl opt">-&gt;</span><span class="hl kwd">releaseFence</span><span class="hl opt">();</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span>bufferFence<span class="hl opt">) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Unexpected valid fence in completed request&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl kwa">return</span> TestPass<span class="hl opt">;</span>
<span class="hl opt">}</span>

<span class="hl kwb">void</span> <span class="hl kwc">FenceTest</span><span class="hl opt">::</span><span class="hl kwd">requestRequeue</span><span class="hl opt">(</span>Request <span class="hl opt">*</span>request<span class="hl opt">)</span>
<span class="hl opt">{</span>
	<span class="hl kwb">const</span> <span class="hl kwc">Request</span><span class="hl opt">::</span>BufferMap <span class="hl opt">&amp;</span>buffers <span class="hl opt">=</span> request<span class="hl opt">-&gt;</span><span class="hl kwd">buffers</span><span class="hl opt">();</span>
	<span class="hl kwb">const</span> Stream <span class="hl opt">*</span>stream <span class="hl opt">=</span> buffers<span class="hl opt">.</span><span class="hl kwd">begin</span><span class="hl opt">()-&gt;</span>first<span class="hl opt">;</span>
	FrameBuffer <span class="hl opt">*</span>buffer <span class="hl opt">=</span> buffers<span class="hl opt">.</span><span class="hl kwd">begin</span><span class="hl opt">()-&gt;</span>second<span class="hl opt">;</span>
	<span class="hl kwb">uint64_t</span> cookie <span class="hl opt">=</span> request<span class="hl opt">-&gt;</span><span class="hl kwd">cookie</span><span class="hl opt">();</span>

	request<span class="hl opt">-&gt;</span><span class="hl kwd">reuse</span><span class="hl opt">();</span>

	<span class="hl kwa">if</span> <span class="hl opt">(</span>cookie <span class="hl opt">==</span> signalledRequestId_ <span class="hl opt">&amp;&amp;</span> setFence_<span class="hl opt">) {</span>
		<span class="hl com">/*</span>
<span class="hl com">		 * The second time this request is queued add a fence to it.</span>
<span class="hl com">		 *</span>
<span class="hl com">		 * The main loop signals it by using a timer to write to the</span>
<span class="hl com">		 * efd2_ file descriptor before the fence expires.</span>
<span class="hl com">		 */</span>
		<span class="hl kwc">std</span><span class="hl opt">::</span>unique_ptr<span class="hl opt">&lt;</span>Fence<span class="hl opt">&gt;</span> fence <span class="hl opt">=</span>
			<span class="hl kwc">std</span><span class="hl opt">::</span>make_unique<span class="hl opt">&lt;</span>Fence<span class="hl opt">&gt;(</span><span class="hl kwc">std</span><span class="hl opt">::</span><span class="hl kwd">move</span><span class="hl opt">(</span>eventFd2_<span class="hl opt">));</span>
		request<span class="hl opt">-&gt;</span><span class="hl kwd">addBuffer</span><span class="hl opt">(</span>stream<span class="hl opt">,</span> buffer<span class="hl opt">,</span> <span class="hl kwc">std</span><span class="hl opt">::</span><span class="hl kwd">move</span><span class="hl opt">(</span>fence<span class="hl opt">));</span>
	<span class="hl opt">}</span> <span class="hl kwa">else</span> <span class="hl opt">{</span>
		<span class="hl com">/* All the other requests continue to operate without fences. */</span>
		request<span class="hl opt">-&gt;</span><span class="hl kwd">addBuffer</span><span class="hl opt">(</span>stream<span class="hl opt">,</span> buffer<span class="hl opt">);</span>
	<span class="hl opt">}</span>

	camera_<span class="hl opt">-&gt;</span><span class="hl kwd">queueRequest</span><span class="hl opt">(</span>request<span class="hl opt">);</span>
<span class="hl opt">}</span>

<span class="hl kwb">void</span> <span class="hl kwc">FenceTest</span><span class="hl opt">::</span><span class="hl kwd">requestComplete</span><span class="hl opt">(</span>Request <span class="hl opt">*</span>request<span class="hl opt">)</span>
<span class="hl opt">{</span>
	<span class="hl kwb">uint64_t</span> cookie <span class="hl opt">=</span> request<span class="hl opt">-&gt;</span><span class="hl kwd">cookie</span><span class="hl opt">();</span>
	completedRequest_ <span class="hl opt">=</span> cookie<span class="hl opt">;</span>

	<span class="hl com">/*</span>
<span class="hl com">	 * The last request is expected to fail as its fence has not been</span>
<span class="hl com">	 * signaled.</span>
<span class="hl com">	 *</span>
<span class="hl com">	 * Validate the fence status but do not re-queue it.</span>
<span class="hl com">	 */</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span>cookie <span class="hl opt">==</span> expiredRequestId_<span class="hl opt">) {</span>
		<span class="hl kwa">if</span> <span class="hl opt">(</span><span class="hl kwd">validateExpiredRequest</span><span class="hl opt">(</span>request<span class="hl opt">) !=</span> TestPass<span class="hl opt">)</span>
			expectedCompletionResult_ <span class="hl opt">=</span> <span class="hl kwa">false</span><span class="hl opt">;</span>

		dispatcher_<span class="hl opt">-&gt;</span><span class="hl kwd">interrupt</span><span class="hl opt">();</span>
		<span class="hl kwa">return</span><span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl com">/* Validate all requests but the last. */</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span><span class="hl kwd">validateRequest</span><span class="hl opt">(</span>request<span class="hl opt">) !=</span> TestPass<span class="hl opt">) {</span>
		expectedCompletionResult_ <span class="hl opt">=</span> <span class="hl kwa">false</span><span class="hl opt">;</span>

		dispatcher_<span class="hl opt">-&gt;</span><span class="hl kwd">interrupt</span><span class="hl opt">();</span>
		<span class="hl kwa">return</span><span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl kwd">requestRequeue</span><span class="hl opt">(</span>request<span class="hl opt">);</span>

	<span class="hl com">/*</span>
<span class="hl com">	 * Interrupt the dispatcher to return control to the main loop and</span>
<span class="hl com">	 * activate the fenceTimer.</span>
<span class="hl com">	 */</span>
	dispatcher_<span class="hl opt">-&gt;</span><span class="hl kwd">interrupt</span><span class="hl opt">();</span>
<span class="hl opt">}</span>

<span class="hl com">/* Callback to signal a fence waiting on the eventfd file descriptor. */</span>
<span class="hl kwb">void</span> <span class="hl kwc">FenceTest</span><span class="hl opt">::</span><span class="hl kwd">signalFence</span><span class="hl opt">()</span>
<span class="hl opt">{</span>
	<span class="hl kwb">uint64_t</span> value <span class="hl opt">=</span> <span class="hl num">1</span><span class="hl opt">;</span>
	<span class="hl kwb">int</span> ret<span class="hl opt">;</span>

	ret <span class="hl opt">=</span> <span class="hl kwd">write</span><span class="hl opt">(</span>efd2_<span class="hl opt">, &amp;</span>value<span class="hl opt">,</span> <span class="hl kwa">sizeof</span><span class="hl opt">(</span>value<span class="hl opt">));</span>
	<span class="hl kwa">if</span> <span class="hl opt">(</span>ret <span class="hl opt">!=</span> <span class="hl kwa">sizeof</span><span class="hl opt">(</span>value<span class="hl opt">))</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Failed to signal fence&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>

	setFence_ <span class="hl opt">=</span> <span class="hl kwa">false</span><span class="hl opt">;</span>
	dispatcher_<span class="hl opt">-&gt;</span><span class="hl kwd">processEvents</span><span class="hl opt">();</span>
<span class="hl opt">}</span>

<span class="hl kwb">int</span> <span class="hl kwc">FenceTest</span><span class="hl opt">::</span><span class="hl kwd">run</span><span class="hl opt">()</span>
<span class="hl opt">{</span>
	<span class="hl kwa">for</span> <span class="hl opt">(</span><span class="hl kwb">const</span> <span class="hl kwc">auto</span> <span class="hl opt">&amp;[</span>i<span class="hl opt">,</span> buffer<span class="hl opt">] :</span> <span class="hl kwc">utils</span><span class="hl opt">::</span><span class="hl kwd">enumerate</span><span class="hl opt">(</span>allocator_<span class="hl opt">-&gt;</span><span class="hl kwd">buffers</span><span class="hl opt">(</span>stream_<span class="hl opt">))) {</span>
		<span class="hl kwc">std</span><span class="hl opt">::</span>unique_ptr<span class="hl opt">&lt;</span>Request<span class="hl opt">&gt;</span> request <span class="hl opt">=</span> camera_<span class="hl opt">-&gt;</span><span class="hl kwd">createRequest</span><span class="hl opt">(</span>i<span class="hl opt">);</span>
		<span class="hl kwa">if</span> <span class="hl opt">(!</span>request<span class="hl opt">) {</span>
			cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Failed to create request&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
			<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
		<span class="hl opt">}</span>

		<span class="hl kwb">int</span> ret<span class="hl opt">;</span>
		<span class="hl kwa">if</span> <span class="hl opt">(</span>i <span class="hl opt">==</span> expiredRequestId_<span class="hl opt">) {</span>
			<span class="hl com">/* This request will have a fence, and it will expire. */</span>
			fence_ <span class="hl opt">=</span> <span class="hl kwc">std</span><span class="hl opt">::</span>make_unique<span class="hl opt">&lt;</span>Fence<span class="hl opt">&gt;(</span><span class="hl kwc">std</span><span class="hl opt">::</span><span class="hl kwd">move</span><span class="hl opt">(</span>eventFd_<span class="hl opt">));</span>
			<span class="hl kwa">if</span> <span class="hl opt">(!</span>fence_<span class="hl opt">-&gt;</span><span class="hl kwd">isValid</span><span class="hl opt">()) {</span>
				cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Fence should be valid&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
				<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
			<span class="hl opt">}</span>

			ret <span class="hl opt">=</span> request<span class="hl opt">-&gt;</span><span class="hl kwd">addBuffer</span><span class="hl opt">(</span>stream_<span class="hl opt">,</span> buffer<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">(),</span> <span class="hl kwc">std</span><span class="hl opt">::</span><span class="hl kwd">move</span><span class="hl opt">(</span>fence_<span class="hl opt">));</span>
		<span class="hl opt">}</span> <span class="hl kwa">else</span> <span class="hl opt">{</span>
			<span class="hl com">/* All other requests will have no Fence. */</span>
			ret <span class="hl opt">=</span> request<span class="hl opt">-&gt;</span><span class="hl kwd">addBuffer</span><span class="hl opt">(</span>stream_<span class="hl opt">,</span> buffer<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">());</span>
		<span class="hl opt">}</span>

		<span class="hl kwa">if</span> <span class="hl opt">(</span>ret<span class="hl opt">) {</span>
			cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Failed to associate buffer with request&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
			<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
		<span class="hl opt">}</span>

		requests_<span class="hl opt">.</span><span class="hl kwd">push_back</span><span class="hl opt">(</span><span class="hl kwc">std</span><span class="hl opt">::</span><span class="hl kwd">move</span><span class="hl opt">(</span>request<span class="hl opt">));</span>
	<span class="hl opt">}</span>

	camera_<span class="hl opt">-&gt;</span>requestCompleted<span class="hl opt">.</span><span class="hl kwd">connect</span><span class="hl opt">(</span><span class="hl kwa">this</span><span class="hl opt">, &amp;</span><span class="hl kwc">FenceTest</span><span class="hl opt">::</span>requestComplete<span class="hl opt">);</span>

	<span class="hl kwa">if</span> <span class="hl opt">(</span>camera_<span class="hl opt">-&gt;</span><span class="hl kwd">start</span><span class="hl opt">()) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Failed to start camera&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl kwa">for</span> <span class="hl opt">(</span><span class="hl kwc">std</span><span class="hl opt">::</span>unique_ptr<span class="hl opt">&lt;</span>Request<span class="hl opt">&gt; &amp;</span>request <span class="hl opt">:</span> requests_<span class="hl opt">) {</span>
		<span class="hl kwa">if</span> <span class="hl opt">(</span>camera_<span class="hl opt">-&gt;</span><span class="hl kwd">queueRequest</span><span class="hl opt">(</span>request<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">())) {</span>
			cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Failed to queue request&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
			<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
		<span class="hl opt">}</span>
	<span class="hl opt">}</span>

	expectedCompletionResult_ <span class="hl opt">=</span> <span class="hl kwa">true</span><span class="hl opt">;</span>

	<span class="hl com">/* This timer serves to signal fences associated with &quot;signalledRequestId_&quot; */</span>
	Timer fenceTimer<span class="hl opt">;</span>
	fenceTimer<span class="hl opt">.</span>timeout<span class="hl opt">.</span><span class="hl kwd">connect</span><span class="hl opt">(</span><span class="hl kwa">this</span><span class="hl opt">, &amp;</span><span class="hl kwc">FenceTest</span><span class="hl opt">::</span>signalFence<span class="hl opt">);</span>

	<span class="hl com">/* Loop for one second. */</span>
	Timer timer<span class="hl opt">;</span>
	timer<span class="hl opt">.</span><span class="hl kwd">start</span><span class="hl opt">(</span><span class="hl num">1000</span>ms<span class="hl opt">);</span>
	<span class="hl kwa">while</span> <span class="hl opt">(</span>timer<span class="hl opt">.</span><span class="hl kwd">isRunning</span><span class="hl opt">() &amp;&amp;</span> expectedCompletionResult_<span class="hl opt">) {</span>
		<span class="hl kwa">if</span> <span class="hl opt">(</span>completedRequest_ <span class="hl opt">==</span> signalledRequestId_ <span class="hl opt">&amp;&amp;</span> setFence_<span class="hl opt">)</span>
			<span class="hl com">/*</span>
<span class="hl com">			 * signalledRequestId_ has just completed and it has</span>
<span class="hl com">			 * been re-queued with a fence. Start the timer to</span>
<span class="hl com">			 * signal the fence in 10 msec.</span>
<span class="hl com">			 */</span>
			fenceTimer<span class="hl opt">.</span><span class="hl kwd">start</span><span class="hl opt">(</span><span class="hl num">10</span>ms<span class="hl opt">);</span>

		dispatcher_<span class="hl opt">-&gt;</span><span class="hl kwd">processEvents</span><span class="hl opt">();</span>
	<span class="hl opt">}</span>

	camera_<span class="hl opt">-&gt;</span>requestCompleted<span class="hl opt">.</span><span class="hl kwd">disconnect</span><span class="hl opt">();</span>

	<span class="hl kwa">if</span> <span class="hl opt">(</span>camera_<span class="hl opt">-&gt;</span><span class="hl kwd">stop</span><span class="hl opt">()) {</span>
		cerr <span class="hl opt">&lt;&lt;</span> <span class="hl str">&quot;Failed to stop camera&quot;</span> <span class="hl opt">&lt;&lt;</span> endl<span class="hl opt">;</span>
		<span class="hl kwa">return</span> TestFail<span class="hl opt">;</span>
	<span class="hl opt">}</span>

	<span class="hl kwa">return</span> expectedCompletionResult_ <span class="hl opt">?</span> TestPass <span class="hl opt">:</span> TestFail<span class="hl opt">;</span>
<span class="hl opt">}</span>

<span class="hl kwd">TEST_REGISTER</span><span class="hl opt">(</span>FenceTest<span class="hl opt">)</span>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.1</a> (<a href='https://git-scm.com/'>git 2.18.0</a>) at 2025-03-18 00:50:37 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>