synthetic-stream-gl.h
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2017 Intel Corporation. All Rights Reserved.
3 
4 #pragma once
5 
6 #include "core/processing.h"
7 #include "image.h"
8 #include "source.h"
9 #include "../include/librealsense2/hpp/rs_frame.hpp"
10 #include "../include/librealsense2/hpp/rs_processing.hpp"
11 #include "../include/librealsense2-gl/rs_processing_gl.hpp"
12 #include "opengl3.h"
13 #include "tiny-profiler.h"
14 
15 #include "concurrency.h"
16 #include <functional>
17 #include <thread>
18 #include <deque>
19 #include <unordered_set>
20 
21 #include "proc/synthetic-stream.h"
22 
23 #define RS2_EXTENSION_VIDEO_FRAME_GL (rs2_extension)(RS2_EXTENSION_COUNT)
24 #define RS2_EXTENSION_DEPTH_FRAME_GL (rs2_extension)(RS2_EXTENSION_COUNT + 1)
25 #define MAX_TEXTURES 2
26 
27 namespace librealsense
28 {
29  namespace gl
30  {
32  {
43  };
44 
46  {
49  int size;
53  };
54 
55  template<class T, int N = 2>
56  class pbo
57  {
58  public:
59  void init(int w, int h)
60  {
61  glGenBuffers(N, pboIds);
62  for (int i = 0; i < N; i++)
63  {
66  glBufferData(GL_PIXEL_PACK_BUFFER, sizeof(T) * w * h, 0, GL_STREAM_READ);
68  }
69 
72  }
73 
74  void query(T* res, int x0, int y0, int w, int h, uint32_t format, uint32_t type)
75  {
76  GLubyte* pData = NULL;
77 
78  int next_idx = (index + 1) % N;
79  glBindBuffer(GL_PIXEL_PACK_BUFFER, pboIds[next_idx]);
81  {
84 
85  glReadPixels(x0, y0, w, h, format, type, 0);
87  }
88 
91  {
93  }
95 
96  if (pData)
97  {
98  memcpy(res, (void*)pData, w * h * sizeof(T));
100  check_gl_error();
101  }
102 
103  index = next_idx;
104  }
105 
106  void reset()
107  {
108  glDeleteBuffers(N, pboIds);
109  }
110 
111  private:
112  uint32_t pboIds[N];
113  int index = 0;
114  };
115 
117 
118  class gpu_object;
119  class gpu_processing_object;
120  class gpu_rendering_object;
121 
122  class context : public std::enable_shared_from_this<context>
123  {
124  public:
125  context(GLFWwindow* share_with, glfw_binding binding);
126 
127  std::shared_ptr<void> begin_session();
128 
129  ~context();
130 
132 
133  private:
134  std::shared_ptr<rs2::visualizer_2d> _vis;
137  std::recursive_mutex _lock;
138  };
139 
140  struct lane
141  {
142  std::unordered_set<gpu_object*> objs;
143  std::mutex mutex;
144  std::atomic_bool active { false };
145  bool use_glsl = false;
146 
148  {
149  std::lock_guard<std::mutex> lock(mutex);
150  objs.insert(obj);
151  }
152 
154  {
155  std::lock_guard<std::mutex> lock(mutex);
156  auto it = objs.find(obj);
157  objs.erase(it);
158  }
159  };
160 
161  // This represents a persistent object that holds context and other GL stuff
162  // The context within it might change, but the lane will remain
163  // This is done to simplify GL objects lifetime management -
164  // Once processing blocks are created and in use, and frames have been distributed
165  // to various queues and variables, it can be very hard to properly refresh
166  // them if context changes (windows closes, resolution change or any other reason)
167 
168  // Processing vs Rendering objects require slightly different handling
169 
171  {
172  public:
173  void register_gpu_object(gpu_rendering_object* obj);
174 
175  void unregister_gpu_object(gpu_rendering_object* obj);
176 
177  void init(glfw_binding binding, bool use_glsl);
178 
179  void shutdown();
180 
181  static rendering_lane& instance();
182 
183  bool is_active() const { return _data.active; }
184  bool glsl_enabled() const { return _data.use_glsl; }
185 
186  static bool is_rendering_thread();
187  protected:
190  };
191 
193  {
194  public:
196  {
197  for (auto i = 0; i < RS2_GL_MATRIX_COUNT; i++)
199  }
202  virtual ~matrix_container() {}
203 
204  private:
206  };
207 
209  {
210  public:
211  static processing_lane& instance();
212 
213  void register_gpu_object(gpu_processing_object* obj);
214 
215  void unregister_gpu_object(gpu_processing_object* obj);
216 
217  void init(GLFWwindow* share_with, glfw_binding binding, bool use_glsl);
218 
219  void shutdown();
220 
221  bool is_active() const { return _data.active; }
222  std::shared_ptr<context> get_context() const
223  {
224  return _ctx;
225  }
226  bool glsl_enabled() const { return _data.use_glsl; }
227  private:
229  std::shared_ptr<context> _ctx;
230  };
231 
233  {
234  private:
235  friend class processing_lane;
236  friend class rendering_lane;
237 
238  void update_gpu_resources(bool use_glsl)
239  {
240  _use_glsl = use_glsl;
241  if (_needs_cleanup.fetch_xor(1))
242  cleanup_gpu_resources();
243  else
244  create_gpu_resources();
245  }
246  protected:
247  gpu_object() = default;
248 
249  virtual void cleanup_gpu_resources() = 0;
250  virtual void create_gpu_resources() = 0;
251 
252  bool glsl_enabled() const { return _use_glsl; }
253 
254  void need_cleanup() { _needs_cleanup = 1; }
255  void use_glsl(bool val) { _use_glsl = val; }
256 
257  private:
258  gpu_object(const gpu_object&) = delete;
259  gpu_object& operator=(const gpu_object&) = delete;
260 
261  std::atomic_int _needs_cleanup { 0 };
262  bool _use_glsl = false;
263  };
264 
266  {
267  public:
269  {
271  }
273  {
275  }
276 
277  protected:
278  void initialize() {
279  use_glsl(rendering_lane::instance().glsl_enabled());
280  if (rendering_lane::instance().is_active())
281  create_gpu_resources();
282  need_cleanup();
283  }
284 
285  template<class T>
287  {
288  if (rendering_lane::instance().is_active())
289  action();
290  }
291  };
292 
294  {
295  public:
297  {
299  }
301  {
303  }
304 
305  void set_context(std::weak_ptr<context> ctx) { _ctx = ctx; }
306  protected:
307  void initialize() {
308  if (processing_lane::instance().is_active())
309  {
311  use_glsl(processing_lane::instance().glsl_enabled());
312  perform_gl_action([this](){
313  create_gpu_resources();
314  }, []{});
315  need_cleanup();
316  }
317  }
318 
319  template<class T, class S>
320  void perform_gl_action(T action, S fallback)
321  {
322  auto ctx = _ctx.lock();
323  if (ctx)
324  {
325  auto session = ctx->begin_session();
326  if (processing_lane::instance().is_active())
327  action();
328  else
329  fallback();
330  }
331  else fallback();
332  }
333 
335  {
336  if (auto ctx = _ctx.lock())
337  return ctx->get_texture_visualizer();
338  else throw std::runtime_error("No context available");
339  }
340  private:
341  std::weak_ptr<context> _ctx;
342  };
343 
345  {
346  public:
347  gpu_section();
348  ~gpu_section();
349 
350  void on_publish();
351  void on_unpublish();
352  void fetch_frame(void* to);
353 
354  bool input_texture(int id, uint32_t* tex);
355  void output_texture(int id, uint32_t* tex, texture_type type);
356 
357  void set_size(uint32_t width, uint32_t height, bool preloaded = false);
358 
359  void cleanup_gpu_resources() override;
360  void create_gpu_resources() override;
361 
362  int get_frame_size() const;
363 
364  bool on_gpu() const { return !backup.get(); }
365 
366  operator bool();
367 
368  private:
371  bool loaded[MAX_TEXTURES];
373  bool backup_content = true;
374  bool preloaded = false;
375  bool initialized = false;
376  std::unique_ptr<uint8_t[]> backup;
377  void ensure_init();
378  };
379 
381  {
382  public:
383  virtual gpu_section& get_gpu_section() = 0;
384  virtual ~gpu_addon_interface() = default;
385  };
386 
387  template<class T>
388  class gpu_addon : public T, public gpu_addon_interface
389  {
390  public:
391  virtual gpu_section& get_gpu_section() override { return _section; }
392  frame_interface* publish(std::shared_ptr<archive_interface> new_owner) override
393  {
394  _section.on_publish();
395  return T::publish(new_owner);
396  }
397  void unpublish() override
398  {
399  _section.on_unpublish();
400  T::unpublish();
401  }
402  const byte* get_frame_data() const override
403  {
404  auto res = T::get_frame_data();
405  _section.fetch_frame((void*)res);
406  return res;
407  }
408  gpu_addon() : T(), _section() {}
410  :T((T&&)std::move(other))
411  {
412  }
414  {
415  return (gpu_addon&)T::operator=((T&&)std::move(other));
416  }
417  private:
419  };
420 
421  class gpu_video_frame : public gpu_addon<video_frame> {};
422  class gpu_points_frame : public gpu_addon<points> {};
423  class gpu_depth_frame : public gpu_addon<depth_frame> {};
424 
425  // Dual processing block is a helper class (TODO: move to core LRS)
426  // that represents several blocks doing the same exact thing
427  // behaving absolutely equally from API point of view,
428  // but only one of them actually getting the calls from frames
429  // This lets us easily create "backup" behaviour where GL block
430  // can fall back on the best CPU implementation if GLSL is not available
432  {
433  public:
434  class bypass_option : public option
435  {
436  public:
438  : _parent(parent), _opt(opt) {}
439 
440  void set(float value) override {
441  // While query and other read operations
442  // will only read from the currently selected
443  // block, setting an option will propogate
444  // to all blocks in the group
445  for(size_t i = 0; i < _parent->_blocks.size(); i++)
446  {
447  if (_parent->_blocks[i]->supports_option(_opt))
448  {
449  _parent->_blocks[i]->get_option(_opt).set(value);
450  }
451  }
452  }
453  float query() const override { return get().query(); }
454  option_range get_range() const override { return get().get_range(); }
455  bool is_enabled() const override { return get().is_enabled(); }
456  bool is_read_only() const override { return get().is_read_only(); }
457  const char* get_description() const override { return get().get_description(); }
458  const char* get_value_description(float v) const override { return get().get_value_description(v); }
459  void enable_recording(std::function<void(const option &)> record_action) override {}
460 
461  option& get() { return _parent->get().get_option(_opt); }
462  const option& get() const { return _parent->get().get_option(_opt); }
463  private:
466  };
467 
468  dual_processing_block() : processing_block("Dual-Purpose Block") {}
469 
471  {
472  for(size_t i = 0; i < _blocks.size(); i++)
473  {
474  index = i;
475  if (_blocks[i]->supports_option(RS2_OPTION_COUNT))
476  {
477  auto val = _blocks[i]->get_option(RS2_OPTION_COUNT).query();
478  if (val > 0.f) break;
479  }
480  }
481 
482  update_info(RS2_CAMERA_INFO_NAME, _blocks[index]->get_info(RS2_CAMERA_INFO_NAME));
483 
484  return *_blocks[index];
485  }
486 
487  void add(std::shared_ptr<processing_block> block)
488  {
489  _blocks.push_back(block);
490 
491  for (int i = 0; i < RS2_OPTION_COUNT; i++)
492  {
493  auto opt = (rs2_option)i;
494  if (block->supports_option(opt))
495  register_option(opt, std::make_shared<bypass_option>(this, opt));
496  }
497 
498  update_info(RS2_CAMERA_INFO_NAME, block->get_info(RS2_CAMERA_INFO_NAME));
499  }
500 
502  {
503  for (auto&& pb : _blocks) pb->set_processing_callback(callback);
504  }
506  {
507  for (auto&& pb : _blocks) pb->set_output_callback(callback);
508  }
509  void invoke(frame_holder frames) override
510  {
511  get().invoke(std::move(frames));
512  }
514  {
515  return get().get_source();
516  }
517  protected:
518  std::vector<std::shared_ptr<processing_block>> _blocks;
519  int index = 0;
520  };
521  }
522 }
static const textual_icon lock
Definition: model-views.h:218
#define glBufferData
void unregister_gpu_object(gpu_object *obj)
static matrix4 identity()
Definition: rendering.h:281
void unregister_gpu_object(gpu_processing_object *obj)
rs2_option
Defines general configuration controls. These can generally be mapped to camera UVC controls...
Definition: rs_option.h:22
virtual gpu_section & get_gpu_section() override
synthetic_source_interface & get_source() override
std::shared_ptr< rs2_frame_callback > frame_callback_ptr
Definition: src/types.h:1071
#define GL_STREAM_READ
const GLfloat * m
Definition: glext.h:6814
std::unique_ptr< uint8_t[]> backup
void update_gpu_resources(bool use_glsl)
GLfloat value
void unregister_gpu_object(gpu_rendering_object *obj)
texture_mapping & rs_format_to_gl_format(rs2_format type)
void add(std::shared_ptr< processing_block > block)
GLdouble GLdouble GLdouble w
void enable_recording(std::function< void(const option &)> record_action) override
void query(T *res, int x0, int y0, int w, int h, uint32_t format, uint32_t type)
#define MAX_TEXTURES
std::unordered_set< gpu_object * > objs
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:1960
GLhandleARB obj
Definition: glext.h:4157
GLenum GLuint id
khronos_uint8_t GLubyte
GLuint index
GLuint GLfloat * val
gpu_addon & operator=(gpu_addon &&other)
std::shared_ptr< rs2::visualizer_2d > _vis
GLdouble f
GLsizei GLenum GLenum * types
static std::thread::id _rendering_thread
usb_device_info get_info(const std::wstring device_wstr)
std::shared_ptr< rs2_frame_processor_callback > frame_processor_callback_ptr
Definition: src/types.h:1072
#define glBindBuffer
unsigned int uint32_t
Definition: stdint.h:80
const byte * get_frame_data() const override
#define GL_UNPACK_ALIGNMENT
#define glPixelStorei
GLint GLsizei GLsizei height
GLint GLint GLsizei GLint GLenum format
void invoke(frame_holder frames) override
rs2::visualizer_2d & get_texture_visualizer()
def callback(frame)
Definition: t265_stereo.py:91
std::shared_ptr< context > get_context() const
GLuint GLfloat x0
Definition: glext.h:9721
void init(void)
Definition: boing.c:180
rs2_format
A stream&#39;s format identifies how binary data is encoded within a frame.
Definition: rs_sensor.h:59
void set_processing_callback(frame_processor_callback_ptr callback) override
std::recursive_mutex _lock
action
Definition: enums.py:62
std::vector< std::shared_ptr< processing_block > > _blocks
bypass_option(dual_processing_block *parent, rs2_option opt)
#define glUnmapBuffer
#define glMapBuffer
#define glDeleteBuffers
void register_gpu_object(gpu_object *obj)
unsigned char byte
Definition: src/types.h:52
const GLuint * textures
static auto it
#define GL_PIXEL_PACK_BUFFER
const char * get_value_description(float v) const override
GLenum type
#define glGenBuffers
void register_gpu_object(gpu_processing_object *obj)
#define GL_READ_ONLY
static rendering_lane & instance()
void perform_gl_action(T action, S fallback)
GLuint GLfloat GLfloat y0
Definition: glext.h:9721
void set_context(std::weak_ptr< context > ctx)
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
void register_gpu_object(gpu_rendering_object *obj)
static processing_lane & instance()
#define NULL
Definition: tinycthread.c:47
rs2_gl_matrix_type
int i
GLuint res
Definition: glext.h:8856
#define GL_PACK_ALIGNMENT
void init(int w, int h)
void set_matrix(rs2_gl_matrix_type type, const rs2::matrix4 &val)
const rs2::matrix4 & get_matrix(rs2_gl_matrix_type type) const
void set_output_callback(frame_callback_ptr callback) override
#define check_gl_error()
Definition: opengl3.h:17
#define glReadPixels
GLdouble v
std::shared_ptr< context > _ctx
struct GLFWwindow GLFWwindow
GLint GLsizei width
frame_interface * publish(std::shared_ptr< archive_interface > new_owner) override


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:50:11