0001-add-starfive-support.patch 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. From 6abadc7414f0fdfea160374326cea32bd2b40d7d Mon Sep 17 00:00:00 2001
  2. From: sw.multimedia <sw.multimedia@starfivetech.com>
  3. Date: Fri, 15 Oct 2021 10:55:01 +0800
  4. Subject: [PATCH] add starfive support
  5. ---
  6. CMakeLists.txt | 2 +-
  7. core/CMakeLists.txt | 2 +-
  8. core/libcamera_app.cpp | 38 ++++--
  9. core/options.hpp | 3 +
  10. preview/CMakeLists.txt | 9 ++
  11. preview/fb_preview.cpp | 289 +++++++++++++++++++++++++++++++++++++++++
  12. preview/preview.cpp | 7 +-
  13. 7 files changed, 338 insertions(+), 12 deletions(-)
  14. create mode 100644 preview/fb_preview.cpp
  15. diff --git a/CMakeLists.txt b/CMakeLists.txt
  16. index 2293211..253ec8d 100644
  17. --- a/CMakeLists.txt
  18. +++ b/CMakeLists.txt
  19. @@ -12,7 +12,7 @@ endif()
  20. set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
  21. set (CMAKE_CXX_STANDARD 17)
  22. set (CMAKE_CXX_FLAGS "-Wall -Wextra -pedantic -Wno-unused-parameter -faligned-new")
  23. -add_definitions(-Werror)
  24. +# add_definitions(-Werror)
  25. add_definitions(-Wfatal-errors)
  26. add_definitions(-D_FILE_OFFSET_BITS=64)
  27. diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
  28. index 1618541..84316b2 100644
  29. --- a/core/CMakeLists.txt
  30. +++ b/core/CMakeLists.txt
  31. @@ -11,6 +11,6 @@ add_library(libcamera_app libcamera_app.cpp post_processor.cpp version.cpp)
  32. add_dependencies(libcamera_app VersionCpp)
  33. set_target_properties(libcamera_app PROPERTIES PREFIX "" IMPORT_PREFIX "")
  34. -target_link_libraries(libcamera_app pthread preview ${LIBCAMERA_LINK_LIBRARIES} ${Boost_LIBRARIES} post_processing_stages)
  35. +target_link_libraries(libcamera_app pthread preview ${LIBCAMERA_LIBRARIES} ${Boost_LIBRARIES} post_processing_stages)
  36. install(TARGETS libcamera_app LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
  37. diff --git a/core/libcamera_app.cpp b/core/libcamera_app.cpp
  38. index 7d4e28f..3c4d862 100644
  39. --- a/core/libcamera_app.cpp
  40. +++ b/core/libcamera_app.cpp
  41. @@ -134,7 +134,12 @@ void LibcameraApp::ConfigureViewfinder()
  42. }
  43. // Now we get to override any of the default settings from the options_->
  44. - configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  45. + std::cout << "viewfinder pixelformat: " << options_->pixelformat << std::endl;
  46. + if (options_->pixelformat.length())
  47. + configuration_->at(0).pixelFormat =
  48. + libcamera::PixelFormat::fromString(options_->pixelformat);
  49. + else
  50. + configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  51. configuration_->at(0).size = size;
  52. if (have_lores_stream)
  53. @@ -143,7 +148,11 @@ void LibcameraApp::ConfigureViewfinder()
  54. lores_size.alignDownTo(2, 2);
  55. if (lores_size.width > size.width || lores_size.height > size.height)
  56. throw std::runtime_error("Low res image larger than viewfinder");
  57. - configuration_->at(1).pixelFormat = libcamera::formats::YUV420;
  58. + if (options_->pixelformat.length())
  59. + configuration_->at(0).pixelFormat =
  60. + libcamera::PixelFormat::fromString(options_->pixelformat);
  61. + else
  62. + configuration_->at(1).pixelFormat = libcamera::formats::YUV420;
  63. configuration_->at(1).size = lores_size;
  64. configuration_->at(1).bufferCount = configuration_->at(0).bufferCount;
  65. }
  66. @@ -186,8 +195,13 @@ void LibcameraApp::ConfigureStill(unsigned int flags)
  67. configuration_->at(0).pixelFormat = libcamera::formats::BGR888;
  68. else if (flags & FLAG_STILL_RGB)
  69. configuration_->at(0).pixelFormat = libcamera::formats::RGB888;
  70. - else
  71. - configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  72. + else {
  73. + if (options_->pixelformat.length())
  74. + configuration_->at(0).pixelFormat =
  75. + libcamera::PixelFormat::fromString(options_->pixelformat);
  76. + else
  77. + configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  78. + }
  79. if ((flags & FLAG_STILL_BUFFER_MASK) == FLAG_STILL_DOUBLE_BUFFER)
  80. configuration_->at(0).bufferCount = 2;
  81. else if ((flags & FLAG_STILL_BUFFER_MASK) == FLAG_STILL_TRIPLE_BUFFER)
  82. @@ -241,7 +255,11 @@ void LibcameraApp::ConfigureVideo(unsigned int flags)
  83. throw std::runtime_error("failed to generate video configuration");
  84. // Now we get to override any of the default settings from the options_->
  85. - configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  86. + if (options_->pixelformat.length())
  87. + configuration_->at(0).pixelFormat =
  88. + libcamera::PixelFormat::fromString(options_->pixelformat);
  89. + else
  90. + configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  91. configuration_->at(0).bufferCount = 6; // 6 buffers is better than 4
  92. if (options_->width)
  93. configuration_->at(0).size.width = options_->width;
  94. @@ -267,7 +285,11 @@ void LibcameraApp::ConfigureVideo(unsigned int flags)
  95. if (lores_size.width > configuration_->at(0).size.width ||
  96. lores_size.height > configuration_->at(0).size.height)
  97. throw std::runtime_error("Low res image larger than video");
  98. - configuration_->at(lores_index).pixelFormat = libcamera::formats::YUV420;
  99. + if (options_->pixelformat.length())
  100. + configuration_->at(0).pixelFormat =
  101. + libcamera::PixelFormat::fromString(options_->pixelformat);
  102. + else
  103. + configuration_->at(lores_index).pixelFormat = libcamera::formats::YUV420;
  104. configuration_->at(lores_index).size = lores_size;
  105. configuration_->at(lores_index).bufferCount = configuration_->at(0).bufferCount;
  106. }
  107. @@ -713,8 +735,8 @@ void LibcameraApp::previewThread()
  108. preview_cond_var_.wait(lock);
  109. }
  110. - if (item.stream->configuration().pixelFormat != libcamera::formats::YUV420)
  111. - throw std::runtime_error("Preview windows only support YUV420");
  112. + // if (item.stream->configuration().pixelFormat != libcamera::formats::YUV420)
  113. + // throw std::runtime_error("Preview windows only support YUV420");
  114. unsigned int w, h, stride;
  115. StreamDimensions(item.stream, &w, &h, &stride);
  116. diff --git a/core/options.hpp b/core/options.hpp
  117. index 447983f..5c68088 100644
  118. --- a/core/options.hpp
  119. +++ b/core/options.hpp
  120. @@ -43,6 +43,8 @@ struct Options
  121. "Set the output image width (0 = use default value)")
  122. ("height", value<unsigned int>(&height)->default_value(0),
  123. "Set the output image height (0 = use default value)")
  124. + ("pixelformat", value<std::string>(&pixelformat),
  125. + "Set the pixelformat name")
  126. ("timeout,t", value<uint64_t>(&timeout)->default_value(5000),
  127. "Time (in ms) for which program runs")
  128. ("output,o", value<std::string>(&output),
  129. @@ -119,6 +121,7 @@ struct Options
  130. std::string post_process_file;
  131. unsigned int width;
  132. unsigned int height;
  133. + std::string pixelformat;
  134. bool rawfull;
  135. bool nopreview;
  136. std::string preview;
  137. diff --git a/preview/CMakeLists.txt b/preview/CMakeLists.txt
  138. index 1a7481f..a772e14 100644
  139. --- a/preview/CMakeLists.txt
  140. +++ b/preview/CMakeLists.txt
  141. @@ -63,6 +63,15 @@ else()
  142. message(STATUS "QT display mode will be unavailable!")
  143. endif()
  144. +set(ENABLE_FB 1)
  145. +if (ENABLE_FB)
  146. + set(SRC ${SRC} fb_preview.cpp)
  147. + set(FB_FOUND 1)
  148. + message(STATUS "FB display mode enabled")
  149. +else()
  150. + message(STATUS "FB display mode will be unavailable!")
  151. +endif()
  152. +
  153. add_library(preview null_preview.cpp ${SRC})
  154. target_link_libraries(preview ${TARGET_LIBS})
  155. diff --git a/preview/fb_preview.cpp b/preview/fb_preview.cpp
  156. new file mode 100644
  157. index 0000000..1a88b79
  158. --- /dev/null
  159. +++ b/preview/fb_preview.cpp
  160. @@ -0,0 +1,289 @@
  161. +/* SPDX-License-Identifier: BSD-2-Clause */
  162. +/*
  163. + * Copyright (C) 2021, Raspberry Pi (Trading) Ltd.
  164. + *
  165. + * null_preview.cpp - dummy "show nothing" preview window.
  166. + */
  167. +
  168. +#include <iostream>
  169. +#include <sys/mman.h>
  170. +#include <stdio.h>
  171. +#include <unistd.h>
  172. +#include <errno.h>
  173. +#include <malloc.h>
  174. +#include <sys/types.h>
  175. +#include <sys/stat.h>
  176. +#include <fcntl.h>
  177. +#include <sys/ioctl.h>
  178. +#include <linux/fb.h>
  179. +#include <string.h>
  180. +#include <malloc.h>
  181. +#include <linux/videodev2.h>
  182. +#include <libcamera/formats.h>
  183. +#include <chrono>
  184. +
  185. +#include "core/options.hpp"
  186. +
  187. +#include "preview.hpp"
  188. +
  189. +#define FBIOPAN_GET_PP_MODE 0x4609
  190. +#define FBIOPAN_SET_PP_MODE 0x460a
  191. +
  192. +enum COLOR_FORMAT {
  193. + COLOR_YUV422_UYVY = 0, // 00={Y1,V0,Y0,U0}
  194. + COLOR_YUV422_VYUY = 1, // 01={Y1,U0,Y0,V0}
  195. + COLOR_YUV422_YUYV = 2, // 10={V0,Y1,U0,Y0}
  196. + COLOR_YUV422_YVYU = 3, // 11={U0,Y1,V0,Y0}
  197. +
  198. + COLOR_YUV420P, // 4
  199. + COLOR_YUV420_NV21, // 5
  200. + COLOR_YUV420_NV12, // 6
  201. +
  202. + COLOR_RGB888_ARGB, // 7
  203. + COLOR_RGB888_ABGR, // 8
  204. + COLOR_RGB888_RGBA, // 9
  205. + COLOR_RGB888_BGRA, // 10
  206. + COLOR_RGB565, // 11
  207. +};
  208. +
  209. +struct pp_video_mode {
  210. + enum COLOR_FORMAT format;
  211. + unsigned int height;
  212. + unsigned int width;
  213. + unsigned int addr;
  214. +};
  215. +
  216. +struct pp_mode {
  217. + char pp_id;
  218. + bool bus_out; /*out to ddr*/
  219. + bool fifo_out; /*out to lcdc*/
  220. + bool inited;
  221. + struct pp_video_mode src;
  222. + struct pp_video_mode dst;
  223. +};
  224. +
  225. +class FbPreview : public Preview
  226. +{
  227. +public:
  228. + FbPreview(Options const *options);
  229. + ~FbPreview();
  230. + void SetInfoText(const std::string &text) override
  231. + {
  232. + std::cout << "Camera fps: " << text << std::endl;
  233. + }
  234. + // Display the buffer. You get given the fd back in the BufferDoneCallback
  235. + // once its available for re-use.
  236. + virtual void Show(int fd, libcamera::Span<uint8_t> span, int width, int height, int stride) override;
  237. + // Reset the preview window, clearing the current buffers and being ready to
  238. + // show new ones.
  239. + void Reset() override {}
  240. + // Return the maximum image size allowed. Zeroes mean "no limit".
  241. + virtual void MaxImageSize(unsigned int &w, unsigned int &h) const override { w = h = 0; }
  242. +
  243. +private:
  244. + int NVResize(unsigned char *inBuf,
  245. + unsigned char *outBuf, int imgWidth, int imgHeight);
  246. + int g_fb_fd;
  247. + int g_stfbc_fd;
  248. + struct fb_var_screeninfo g_vinfo;
  249. + struct fb_fix_screeninfo g_finfo;
  250. + unsigned char *g_fb_buf;
  251. + unsigned char *tmpBuf;
  252. + unsigned int g_screensize;
  253. + enum COLOR_FORMAT pixformat;
  254. +};
  255. +
  256. +static enum COLOR_FORMAT v4l2fmt_to_fbfmt(unsigned int format)
  257. +{
  258. + enum COLOR_FORMAT pixformat = COLOR_RGB565;
  259. +
  260. + switch (format) {
  261. + case V4L2_PIX_FMT_RGB565:
  262. + pixformat = COLOR_RGB565;
  263. + break;
  264. + case V4L2_PIX_FMT_RGB24:
  265. + pixformat = COLOR_RGB888_ARGB;
  266. + break;
  267. + case V4L2_PIX_FMT_YUV420:
  268. + pixformat = COLOR_YUV420P;
  269. + break;
  270. + case V4L2_PIX_FMT_YUYV:
  271. + pixformat = COLOR_YUV422_YUYV;
  272. + break;
  273. + case V4L2_PIX_FMT_NV21:
  274. + pixformat = COLOR_YUV420_NV21;
  275. + break;
  276. + case V4L2_PIX_FMT_NV12:
  277. + pixformat = COLOR_YUV420_NV12;
  278. + break;
  279. + case V4L2_PIX_FMT_YVYU:
  280. + pixformat = COLOR_YUV422_YVYU;
  281. + break;
  282. + default:
  283. + pixformat = COLOR_RGB565;
  284. + break;
  285. + }
  286. +
  287. + return pixformat;
  288. +}
  289. +
  290. +FbPreview::FbPreview(Options const *options) : Preview(options)
  291. +{
  292. + g_fb_fd = open("/dev/fb0", O_RDWR);
  293. + if (g_fb_fd == -1)
  294. + throw std::runtime_error("Couldn't open fb display");
  295. + g_stfbc_fd = open("/dev/stfbcdev", O_RDWR);
  296. + if (g_stfbc_fd == -1)
  297. + throw std::runtime_error("Couldn't open stfbcdev display");
  298. +
  299. + struct pp_mode pp_info[3];
  300. + libcamera::PixelFormat pixelFormat =
  301. + libcamera::PixelFormat::fromString(options_->pixelformat);
  302. +
  303. + if (pixelFormat.fourcc() != V4L2_PIX_FMT_NV12)
  304. + throw std::runtime_error("FB onlu support NV12 display");
  305. +
  306. + pixformat = v4l2fmt_to_fbfmt(pixelFormat.fourcc());
  307. + if (-1 == ioctl(g_stfbc_fd, FBIOPAN_GET_PP_MODE, &pp_info[0]))
  308. + throw std::runtime_error("Error reading variable information.");
  309. +
  310. + std::cout << "get pp format : "
  311. + << pp_info[1].src.format
  312. + << std::endl;
  313. +
  314. + pp_info[1].src.format = pixformat;
  315. +
  316. + if (-1 == ioctl(g_stfbc_fd, FBIOPAN_SET_PP_MODE, &pp_info[0]))
  317. + throw std::runtime_error("Error reading variable information.");
  318. +
  319. + if (-1 == ioctl(g_stfbc_fd, FBIOPAN_GET_PP_MODE, &pp_info[0]))
  320. + throw std::runtime_error("Error reading variable information.");
  321. +
  322. + std::cout << "get pp format : "
  323. + << pp_info[1].src.format
  324. + << std::endl;
  325. +
  326. + pixformat = pp_info[1].src.format;
  327. +
  328. + // Get fixed screen information
  329. + if (-1 == ioctl(g_fb_fd, FBIOGET_FSCREENINFO, &g_finfo))
  330. + throw std::runtime_error("Error reading fixed information.");
  331. +
  332. + // Get variable screen information
  333. + if (-1 == ioctl(g_fb_fd, FBIOGET_VSCREENINFO, &g_vinfo))
  334. + throw std::runtime_error("Error reading variable information.");
  335. +
  336. + std::cout << "g_vinfo.xres = " << g_vinfo.xres
  337. + << ", g_vinfo.yres = " << g_vinfo.yres
  338. + << ", grayscale = " << g_vinfo.grayscale
  339. + << std::endl;
  340. + std::cout << "g_vinfo.xoffset = " << g_vinfo.xoffset
  341. + << ", g_vinfo.yoffset = " << g_vinfo.yoffset
  342. + << std::endl;
  343. + std::cout << "g_vinfo.bits_per_pixel = " << g_vinfo.bits_per_pixel
  344. + << ", g_finfo.line_length = " << g_finfo.line_length
  345. + << std::endl;
  346. +
  347. + g_screensize = g_vinfo.xres * g_vinfo.yres * g_vinfo.bits_per_pixel / 8;
  348. + g_fb_buf = (unsigned char *)mmap(NULL, g_screensize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fb_fd, 0);
  349. + if (g_fb_buf == (void *)(-1))
  350. + throw std::runtime_error("Error: failed to map framebuffer device to memory.");
  351. +
  352. + memset(g_fb_buf, 0x00, g_screensize);
  353. + tmpBuf = static_cast<unsigned char *>(malloc(g_screensize));
  354. + if (!tmpBuf)
  355. + throw std::runtime_error("Error: failed to malloc memory.");
  356. + memset(tmpBuf, 0x00, g_screensize);
  357. +
  358. + if (options->verbose)
  359. + std::cout << "Running fb preview window" << std::endl;
  360. +}
  361. +
  362. +FbPreview::~FbPreview()
  363. +{
  364. + free(tmpBuf);
  365. + munmap((void *)g_fb_buf, g_screensize);
  366. + close(g_fb_fd);
  367. + close(g_stfbc_fd);
  368. + std::cout << "fb preview window ~FbPreview" << std::endl;
  369. +}
  370. +
  371. +int FbPreview::NVResize(unsigned char *inBuf,
  372. + unsigned char *outBuf, int imgWidth, int imgHeight)
  373. +{
  374. + int rows, cols;
  375. + unsigned char *OutNVdata, *InNVdata;
  376. + int Ypos, Upos, Vpos;
  377. + int fb_Ypos, fb_Upos, fb_Vpos;
  378. + int width, height;
  379. + int x_offset, y_offset;
  380. + unsigned int start_timems;
  381. + unsigned int end_timems;
  382. + struct timeval ts_start, ts_end;
  383. +
  384. + width = imgWidth > g_vinfo.xres ? g_vinfo.xres : imgWidth;
  385. + height = imgHeight > g_vinfo.yres ? g_vinfo.yres : imgHeight;
  386. + x_offset = (g_vinfo.xres - width) / 2;
  387. + y_offset = (g_vinfo.yres - height) / 2;
  388. +
  389. + InNVdata = inBuf;
  390. + OutNVdata = tmpBuf;
  391. +
  392. + if (imgWidth == g_vinfo.xres) {
  393. + fb_Ypos = y_offset * g_vinfo.xres + x_offset;
  394. + fb_Upos = (y_offset / 2 * g_vinfo.xres / 2 + x_offset / 2) * 2;
  395. + fb_Upos = g_vinfo.xres * g_vinfo.yres + fb_Upos;
  396. + Upos = imgWidth * imgHeight;
  397. + memcpy(&tmpBuf[fb_Ypos], inBuf, imgWidth * height);
  398. + memcpy(&tmpBuf[fb_Upos], &inBuf[Upos], imgWidth * height / 2);
  399. + memcpy(&outBuf[fb_Ypos], &tmpBuf[fb_Ypos], imgWidth * height * 2);
  400. + memcpy(&outBuf[fb_Upos], &tmpBuf[fb_Upos], imgWidth * height / 2);
  401. + return 0;
  402. + }
  403. +
  404. + /* two bytes for every pixels */
  405. + for(rows = 0; rows < height; rows+=2)
  406. + {
  407. + // g_vinfo.xres, g_vinfo.yres g_vinfo.bits_per_pixel
  408. + fb_Ypos = ((rows + y_offset) * g_vinfo.xres + x_offset);
  409. + fb_Upos = ((rows + y_offset) / 2 * g_vinfo.xres / 2 + x_offset / 2) * 2;
  410. + fb_Upos = g_vinfo.xres * g_vinfo.yres + fb_Upos;
  411. + fb_Vpos = fb_Upos + 1;
  412. +
  413. + Ypos = rows * imgWidth;
  414. + Upos = imgWidth * imgHeight + Ypos / 2;
  415. + Vpos = Upos + 1;
  416. + memcpy(&OutNVdata[fb_Ypos], &InNVdata[Ypos], width);
  417. + memcpy(&OutNVdata[fb_Ypos+g_vinfo.xres], &InNVdata[Ypos+imgWidth], width);
  418. +
  419. + memcpy(&OutNVdata[fb_Upos], &InNVdata[Upos], width);
  420. + }
  421. +
  422. + memcpy(outBuf, tmpBuf, g_screensize);
  423. +
  424. + return 0;
  425. +}
  426. +
  427. +void FbPreview::Show(int fd, libcamera::Span<uint8_t> span, int width, int height, int stride)
  428. +{
  429. + int imgsize = stride * height + stride * height / 2;
  430. + auto startTime = std::chrono::high_resolution_clock::now();
  431. +
  432. + if (pixformat == COLOR_YUV420_NV21 || pixformat == COLOR_YUV420_NV12)
  433. + NVResize(span.data(), g_fb_buf, width, height);
  434. + else
  435. + std::cout << "FbPreview unsupport pixformat: " << pixformat << std::endl;
  436. +
  437. + auto endTime = std::chrono::high_resolution_clock::now();
  438. +
  439. + std::chrono::duration<double,std::ratio<1,1000000>> duration_mcs =
  440. + std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1,1000000>>>(endTime-startTime);
  441. + std::cout << "FbPreview copy fps " << 1000000 / duration_mcs.count() << "." << std::endl;
  442. +
  443. + done_callback_(fd);
  444. +}
  445. +
  446. +Preview *make_fb_preview(Options const *options)
  447. +{
  448. + return new FbPreview(options);
  449. +}
  450. diff --git a/preview/preview.cpp b/preview/preview.cpp
  451. index 68d193a..0086d83 100644
  452. --- a/preview/preview.cpp
  453. +++ b/preview/preview.cpp
  454. @@ -13,6 +13,7 @@ Preview *make_null_preview(Options const *options);
  455. Preview *make_egl_preview(Options const *options);
  456. Preview *make_drm_preview(Options const *options);
  457. Preview *make_qt_preview(Options const *options);
  458. +Preview *make_fb_preview(Options const *options);
  459. Preview *make_preview(Options const *options)
  460. {
  461. @@ -48,8 +49,10 @@ Preview *make_preview(Options const *options)
  462. }
  463. catch (std::exception const &e)
  464. {
  465. - std::cout << "Preview window unavailable" << std::endl;
  466. - return make_null_preview(options);
  467. + std::cout << "FB Preview window." << std::endl;
  468. + return make_fb_preview(options);
  469. + // std::cout << "Preview window unavailable" << std::endl;
  470. + // return make_null_preview(options);
  471. }
  472. }
  473. }
  474. --
  475. 2.17.1