Panda3D
displayRegion.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file displayRegion.cxx
10  * @author cary
11  * @date 1999-02-10
12  */
13 
14 #include "displayRegion.h"
15 #include "stereoDisplayRegion.h"
16 #include "graphicsEngine.h"
17 #include "graphicsOutput.h"
18 #include "config_display.h"
19 #include "texture.h"
20 #include "camera.h"
21 #include "dcast.h"
22 #include "pnmImage.h"
23 
24 #include <time.h>
25 
26 using std::string;
27 
28 TypeHandle DisplayRegion::_type_handle;
29 TypeHandle DisplayRegionPipelineReader::_type_handle;
30 
31 /**
32  *
33  */
34 DisplayRegion::
35 DisplayRegion(GraphicsOutput *window, const LVecBase4 &dimensions) :
36  _window(window),
37  _incomplete_render(true),
38  _texture_reload_priority(0),
39  _cull_region_pcollector("Cull:Invalid"),
40  _draw_region_pcollector("Draw:Invalid")
41 {
42  _screenshot_buffer_type = window->get_draw_buffer_type();
43  _draw_buffer_type = window->get_draw_buffer_type();
44  set_num_regions(1);
45  set_dimensions(0, dimensions);
46  compute_pixels_all_stages();
47 
48  _window->add_display_region(this);
49 }
50 
51 /**
52  *
53  */
54 DisplayRegion::
55 ~DisplayRegion() {
56  cleanup();
57 
58  // The window pointer should already have been cleared by the time the
59  // DisplayRegion destructs (since the GraphicsOutput class keeps a reference
60  // count on the DisplayRegion).
61  nassertv(_window == nullptr);
62 }
63 
64 /**
65  * Cleans up some pointers associated with the DisplayRegion to help reduce
66  * the chance of memory leaks due to circular reference counts.
67  */
68 void DisplayRegion::
70  CDStageWriter cdata(_cycler, 0);
71  if (cdata->_camera_node != nullptr) {
72  // We need to tell the old camera we're not using it anymore.
73  cdata->_camera_node->remove_display_region(this);
74  }
75  cdata->_camera_node = nullptr;
76  cdata->_camera = NodePath();
77 
78  CDCullWriter cdata_cull(_cycler_cull, true);
79  cdata_cull->_cull_result = nullptr;
80 }
81 
82 /**
83  * Sets the lens index, allows for multiple lenses to be attached to a camera.
84  * This is useful for a variety of setups, such as fish eye rendering. The
85  * default is 0.
86  *
87  * Don't call this in a downstream thread unless you don't mind it blowing
88  * away other changes you might have recently made in an upstream thread.
89  */
90 void DisplayRegion::
91 set_lens_index(int index) {
92  Thread *current_thread = Thread::get_current_thread();
93  CDWriter cdata(_cycler, true, current_thread);
94  cdata->_lens_index = index;
95 }
96 
97 /**
98  * Changes the portion of the framebuffer this DisplayRegion corresponds to.
99  * The parameters range from 0 to 1, where 0,0 is the lower left corner and
100  * 1,1 is the upper right; (0, 1, 0, 1) represents the whole screen.
101  *
102  * Don't call this in a downstream thread unless you don't mind it blowing
103  * away other changes you might have recently made in an upstream thread.
104  */
105 void DisplayRegion::
106 set_dimensions(int i, const LVecBase4 &dimensions) {
107  Thread *current_thread = Thread::get_current_thread();
108  CDWriter cdata(_cycler, true, current_thread);
109 
110  cdata->_regions[i]._dimensions = dimensions;
111 
112  if (_window != nullptr && _window->has_size()) {
113  do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(), cdata);
114  }
115 }
116 
117 /**
118  * Returns the GraphicsPipe that this DisplayRegion is ultimately associated
119  * with, or NULL if no pipe is associated.
120  */
121 GraphicsPipe *DisplayRegion::
122 get_pipe() const {
123  return (_window != nullptr) ? _window->get_pipe() : nullptr;
124 }
125 
126 /**
127  * Returns true if this is a StereoDisplayRegion, false otherwise.
128  */
129 bool DisplayRegion::
130 is_stereo() const {
131  return false;
132 }
133 
134 /**
135  * Sets the camera that is associated with this DisplayRegion. There is a
136  * one-to-many association between cameras and DisplayRegions; one camera may
137  * be shared by multiple DisplayRegions.
138  *
139  * The camera is actually set via a NodePath, which clarifies which instance
140  * of the camera (if there happen to be multiple instances) we should use.
141  *
142  * Don't call this in a downstream thread unless you don't mind it blowing
143  * away other changes you might have recently made in an upstream thread.
144  */
145 void DisplayRegion::
146 set_camera(const NodePath &camera) {
147  CDWriter cdata(_cycler, true);
148 
149  Camera *camera_node = nullptr;
150  if (!camera.is_empty()) {
151  DCAST_INTO_V(camera_node, camera.node());
152  }
153 
154  if (camera_node != cdata->_camera_node) {
155  // Note that these operations on the DisplayRegion are not pipelined: they
156  // operate across all pipeline stages. Since we have already asserted we
157  // are running in pipeline stage 0, no problem.
158  if (cdata->_camera_node != nullptr) {
159  // We need to tell the old camera we're not using him anymore.
160  cdata->_camera_node->remove_display_region(this);
161  }
162  cdata->_camera_node = camera_node;
163  if (cdata->_camera_node != nullptr) {
164  // Now tell the new camera we are using him.
165  cdata->_camera_node->add_display_region(this);
166  }
167  }
168 
169  cdata->_camera = camera;
170 }
171 
172 /**
173  * Sets the active flag associated with the DisplayRegion. If the
174  * DisplayRegion is marked inactive, nothing is rendered.
175  *
176  * Don't call this in a downstream thread unless you don't mind it blowing
177  * away other changes you might have recently made in an upstream thread.
178  */
179 void DisplayRegion::
180 set_active(bool active) {
181  Thread *current_thread = Thread::get_current_thread();
182  CDWriter cdata(_cycler, true, current_thread);
183 
184  if (active != cdata->_active) {
185  cdata->_active = active;
186  win_display_regions_changed();
187  }
188 }
189 
190 /**
191  * Sets the sort value associated with the DisplayRegion. Within a window,
192  * DisplayRegions will be rendered in order from the lowest sort value to the
193  * highest.
194  *
195  * Don't call this in a downstream thread unless you don't mind it blowing
196  * away other changes you might have recently made in an upstream thread.
197  */
198 void DisplayRegion::
199 set_sort(int sort) {
200  Thread *current_thread = Thread::get_current_thread();
201  CDWriter cdata(_cycler, true, current_thread);
202 
203  if (sort != cdata->_sort) {
204  cdata->_sort = sort;
205  win_display_regions_changed();
206  }
207 }
208 
209 /**
210  * Specifies whether the DisplayRegion represents the left or right channel of
211  * a stereo pair, or whether it is a normal, monocular image. This
212  * automatically adjusts the lens that is used to render to this DisplayRegion
213  * to its left or right eye, according to the lens's stereo properties.
214  *
215  * When the DisplayRegion is attached to a stereo window (one for which
216  * is_stereo() returns true), this also specifies which physical channel the
217  * DisplayRegion renders to.
218  *
219  * Normally you would create at least two DisplayRegions for a stereo window,
220  * one for each of the left and right channels. The two DisplayRegions may
221  * share the same camera (and thus the same lens); this parameter is used to
222  * control the exact properties of the lens when it is used to render into
223  * this DisplayRegion.
224  *
225  * Also see the StereoDisplayRegion, which automates managing a pair of
226  * left/right DisplayRegions.
227  *
228  * An ordinary DisplayRegion may be set to SC_mono, SC_left, or SC_right. You
229  * may set SC_stereo only on a StereoDisplayRegion.
230  *
231  * This call also resets tex_view_offset to its default value, which is 0 for
232  * the left eye or 1 for the right eye of a stereo display region, or 0 for a
233  * mono display region.
234  */
235 void DisplayRegion::
236 set_stereo_channel(Lens::StereoChannel stereo_channel) {
237  nassertv(is_stereo() || stereo_channel != Lens::SC_stereo);
238 
239  nassertv(Thread::get_current_pipeline_stage() == 0);
240 
241  CDWriter cdata(_cycler);
242  cdata->_stereo_channel = stereo_channel;
243  cdata->_tex_view_offset = (stereo_channel == Lens::SC_right) ? 1 : 0;
244 }
245 
246 /**
247  * Sets the current texture view offset for this DisplayRegion. This is
248  * normally set to zero. If nonzero, it is used to select a particular view
249  * of any multiview textures that are rendered within this DisplayRegion.
250  *
251  * For a StereoDisplayRegion, this is normally 0 for the left eye, and 1 for
252  * the right eye, to support stereo textures. This is set automatically when
253  * you call set_stereo_channel().
254  */
255 void DisplayRegion::
256 set_tex_view_offset(int tex_view_offset) {
257  nassertv(Thread::get_current_pipeline_stage() == 0);
258 
259  CDWriter cdata(_cycler);
260  cdata->_tex_view_offset = tex_view_offset;
261 }
262 
263 /**
264  * Sets the incomplete_render flag. When this is true, the frame will be
265  * rendered even if some of the geometry or textures in the scene are not
266  * available (e.g. they have been temporarily paged out). When this is
267  * false, the frame will be held up while this data is reloaded.
268  *
269  * This flag may also be set on the GraphicsStateGuardian. It will be
270  * considered true for a given DisplayRegion only if it is true on both the
271  * GSG and on the DisplayRegion.
272  *
273  * See GraphicsStateGuardian::set_incomplete_render() for more detail.
274  */
275 void DisplayRegion::
276 set_incomplete_render(bool incomplete_render) {
277  _incomplete_render = incomplete_render;
278 }
279 
280 /**
281  * Specifies an integer priority which is assigned to any asynchronous texture
282  * reload requests spawned while processing this DisplayRegion. This controls
283  * which textures are loaded first when multiple textures need to be reloaded
284  * at once; it also controls the relative priority between asynchronous
285  * texture loads and asynchronous model or animation loads.
286  *
287  * Specifying a larger number here makes the textures rendered by this
288  * DisplayRegion load up first. This may be particularly useful to do, for
289  * instance, for the DisplayRegion that renders the gui.
290  */
291 void DisplayRegion::
292 set_texture_reload_priority(int texture_reload_priority) {
293  _texture_reload_priority = texture_reload_priority;
294 }
295 
296 /**
297  * Specifies the CullTraverser that will be used to draw the contents of this
298  * DisplayRegion. Normally the default CullTraverser is sufficient, but this
299  * may be changed to change the default cull behavior.
300  */
301 void DisplayRegion::
303  _trav = trav;
304 }
305 
306 /**
307  * Returns the CullTraverser that will be used to draw the contents of this
308  * DisplayRegion.
309  */
310 CullTraverser *DisplayRegion::
311 get_cull_traverser() {
312  if (_trav == nullptr) {
313  _trav = new CullTraverser;
314  }
315  return _trav;
316 }
317 
318 /**
319  * This is a special parameter that is only used when rendering the faces of a
320  * cube map or multipage and/or multiview texture.
321  *
322  * This sets up the DisplayRegion to render to the ith page and jth view of
323  * its associated texture(s); the value must be consistent with the range of
324  * values availble to the texture. A normal DisplayRegion that is not
325  * associated with any particular page should be set to page -1 and view 0.
326  *
327  * This is particularly useful when rendering cube maps and/or stereo
328  * textures.
329  *
330  * Don't call this in a downstream thread unless you don't mind it blowing
331  * away other changes you might have recently made in an upstream thread.
332  */
333 void DisplayRegion::
334 set_target_tex_page(int page) {
335  Thread *current_thread = Thread::get_current_thread();
336  CDWriter cdata(_cycler, true, current_thread);
337  cdata->_target_tex_page = page;
338 }
339 
340 /**
341  *
342  */
343 void DisplayRegion::
344 output(std::ostream &out) const {
345  CDReader cdata(_cycler);
346  out << "DisplayRegion(" << cdata->_regions[0]._dimensions
347  << ")=pixels(" << cdata->_regions[0]._pixels << ")";
348 }
349 
350 /**
351  * Synthesizes a suitable default filename for passing to save_screenshot().
352  *
353  * The default filename is generated from the supplied prefix and from the
354  * Config variable screenshot-filename, which contains the following strings:
355  *
356  * %~p - the supplied prefix %~f - the frame count %~e - the value of
357  * screenshot-extension All other % strings in strftime().
358  */
360 make_screenshot_filename(const string &prefix) {
361  time_t now = time(nullptr);
362  struct tm *ttm = localtime(&now);
363  int frame_count = ClockObject::get_global_clock()->get_frame_count();
364 
365  static const int buffer_size = 1024;
366  char buffer[buffer_size];
367 
368  std::ostringstream filename_strm;
369 
370  size_t i = 0;
371  while (i < screenshot_filename.length()) {
372  char ch1 = screenshot_filename[i++];
373  if (ch1 == '%' && i < screenshot_filename.length()) {
374  char ch2 = screenshot_filename[i++];
375  if (ch2 == '~' && i < screenshot_filename.length()) {
376  char ch3 = screenshot_filename[i++];
377  switch (ch3) {
378  case 'p':
379  filename_strm << prefix;
380  break;
381 
382  case 'f':
383  filename_strm << frame_count;
384  break;
385 
386  case 'e':
387  filename_strm << screenshot_extension;
388  break;
389  }
390 
391  } else {
392  // Use strftime() to decode the percent code.
393  char format[3] = {'%', ch2, '\0'};
394  if (strftime(buffer, buffer_size, format, ttm)) {
395  for (char *b = buffer; *b != '\0'; b++) {
396  switch (*b) {
397  case ' ':
398  case ':':
399  case '/':
400  filename_strm << '-';
401  break;
402 
403  case '\n':
404  break;
405 
406  default:
407  filename_strm << *b;
408  }
409  }
410  }
411  }
412  } else {
413  filename_strm << ch1;
414  }
415  }
416 
417  return Filename(filename_strm.str());
418 }
419 
420 
421 /**
422  * Saves a screenshot of the region to a default filename, and returns the
423  * filename, or empty string if the screenshot failed. The filename is
424  * generated by make_screenshot_filename().
425  */
427 save_screenshot_default(const string &prefix) {
428  Filename filename = make_screenshot_filename(prefix);
429  if (save_screenshot(filename)) {
430  return filename;
431  }
432  return Filename();
433 }
434 
435 /**
436  * Saves a screenshot of the region to the indicated filename. Returns true
437  * on success, false on failure.
438  */
439 bool DisplayRegion::
440 save_screenshot(const Filename &filename, const string &image_comment) {
441  PNMImage image;
442  if (!get_screenshot(image)) {
443  return false;
444  }
445 
446  image.set_comment(image_comment);
447  if (!image.write(filename)) {
448  return false;
449  }
450  return true;
451 }
452 
453 /**
454  * Captures the most-recently rendered image from the framebuffer into the
455  * indicated PNMImage. Returns true on success, false on failure.
456  */
457 bool DisplayRegion::
459  PT(Texture) tex = get_screenshot();
460 
461  if (tex == nullptr) {
462  return false;
463  }
464 
465  if (!tex->store(image)) {
466  return false;
467  }
468 
469  return true;
470 }
471 
472 /**
473  * Captures the most-recently rendered image from the framebuffer and returns
474  * it as a Texture, or NULL on failure.
475  */
477 get_screenshot() {
478  Thread *current_thread = Thread::get_current_thread();
479 
480  GraphicsOutput *window = get_window();
481  nassertr(window != nullptr, nullptr);
482 
483  GraphicsStateGuardian *gsg = window->get_gsg();
484  nassertr(gsg != nullptr, nullptr);
485 
486  // Are we on the draw thread?
487  if (gsg->get_threading_model().get_draw_stage() != current_thread->get_pipeline_stage()) {
488  // Ask the engine to do on the draw thread.
489  GraphicsEngine *engine = window->get_engine();
490  return engine->do_get_screenshot(this, gsg);
491  }
492 
493  // We are on the draw thread.
494  if (!window->begin_frame(GraphicsOutput::FM_refresh, current_thread)) {
495  return nullptr;
496  }
497 
498  {
499  // Make sure that the correct viewport is active.
500  DisplayRegionPipelineReader dr_reader(this, current_thread);
501  gsg->prepare_display_region(&dr_reader);
502  }
503 
504  PT(Texture) tex = new Texture;
505 
507  _window->get_fb_properties());
508  if (!gsg->framebuffer_copy_to_ram(tex, 0, -1, this, buffer)) {
509  return nullptr;
510  }
511 
512  window->end_frame(GraphicsOutput::FM_refresh, current_thread);
513 
514  return tex;
515 }
516 
517 /**
518  * Returns a special scene graph constructed to represent the results of the
519  * last frame's cull operation.
520  *
521  * This will be a hierarchy of nodes, one node for each bin, each of which
522  * will in term be a parent of a number of GeomNodes, representing the
523  * geometry drawn in each bin.
524  *
525  * This is useful mainly for high-level debugging and abstraction tools; it
526  * should not be mistaken for the low-level cull result itself, which is
527  * constructed and maintained internally. No such scene graph is normally
528  * constructed during the rendering of a frame; this is an artificial
529  * construct created for the purpose of making it easy to analyze the results
530  * of the cull operation.
531  */
532 PT(PandaNode) DisplayRegion::
533 make_cull_result_graph() {
534  CullResult *cull_result = get_cull_result(Thread::get_current_thread());
535  if (cull_result == nullptr) {
536  return nullptr;
537  }
538  return cull_result->make_result_graph();
539 }
540 
541 /**
542  * Computes the pixel locations of the DisplayRegion within its window. The
543  * DisplayRegion will request the size from the window.
544  */
545 void DisplayRegion::
547  if (_window != nullptr) {
548  CDWriter cdata(_cycler, false);
549  for (size_t i = 0; i < cdata->_regions.size(); ++i) {
550  do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(),
551  cdata);
552  }
553  }
554 }
555 
556 /**
557  * Computes the pixel locations of the DisplayRegion within its window. The
558  * DisplayRegion will request the size from the window.
559  */
560 void DisplayRegion::
562  if (_window != nullptr) {
563  OPEN_ITERATE_ALL_STAGES(_cycler) {
564  CDStageWriter cdata(_cycler, pipeline_stage);
565  for (size_t i = 0; i < cdata->_regions.size(); ++i) {
566  do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(),
567  cdata);
568  }
569  }
570  CLOSE_ITERATE_ALL_STAGES(_cycler);
571  }
572 }
573 
574 /**
575  * Computes the pixel locations of the DisplayRegion within its window, given
576  * the size of the window in pixels.
577  */
578 void DisplayRegion::
579 compute_pixels(int x_size, int y_size) {
580  CDWriter cdata(_cycler, false);
581  for (size_t i = 0; i < cdata->_regions.size(); ++i) {
582  do_compute_pixels(i, x_size, y_size, cdata);
583  }
584 }
585 
586 /**
587  * Performs a compute_pixels() operation for all stages of the pipeline. This
588  * is appropriate, for instance, when a window changes sizes, since this is a
589  * global operation; and you want the new window size to be immediately
590  * available even to the downstream stages.
591  */
592 void DisplayRegion::
593 compute_pixels_all_stages(int x_size, int y_size) {
594  OPEN_ITERATE_ALL_STAGES(_cycler) {
595  CDStageWriter cdata(_cycler, pipeline_stage);
596  for (size_t i = 0; i < cdata->_regions.size(); ++i) {
597  do_compute_pixels(i, x_size, y_size, cdata);
598  }
599  }
600  CLOSE_ITERATE_ALL_STAGES(_cycler);
601 }
602 
603 /**
604  * Returns true if a call to set_pixel_zoom() will be respected, false if it
605  * will be ignored. If this returns false, then get_pixel_factor() will
606  * always return 1.0, regardless of what value you specify for
607  * set_pixel_zoom().
608  *
609  * This may return false if the underlying renderer doesn't support pixel
610  * zooming, or if you have called this on a DisplayRegion that doesn't have
611  * both set_clear_color() and set_clear_depth() enabled.
612  */
613 bool DisplayRegion::
615  if (_window != nullptr) {
616  if (_window->supports_pixel_zoom()) {
618  }
619  }
620  return false;
621 }
622 
623 /**
624  * Intended to be called when the active state on a nested channel or layer or
625  * display region changes, forcing the window to recompute its list of active
626  * display regions. It is assumed the lock is already held.
627  */
628 void DisplayRegion::
629 win_display_regions_changed() {
630  if (_window != nullptr) {
631  _window->win_display_regions_changed();
632  }
633 }
634 
635 /**
636  * The private implementation of compute_pixels, this assumes that we already
637  * have the lock.
638  */
639 void DisplayRegion::
640 do_compute_pixels(int i, int x_size, int y_size, CData *cdata) {
641  if (display_cat.is_debug()) {
642  display_cat.debug()
643  << "DisplayRegion::do_compute_pixels(" << x_size << ", " << y_size << ")\n";
644  }
645 
646  Region &region = cdata->_regions[i];
647 
648  region._pixels[0] = int((region._dimensions[0] * x_size) + 0.5);
649  region._pixels[1] = int((region._dimensions[1] * x_size) + 0.5);
650  region._pixels_i[0] = region._pixels[0];
651  region._pixels_i[1] = region._pixels[1];
652 
653  nassertv(_window != nullptr);
654  if (_window->get_inverted()) {
655  // The window is inverted; compute the DisplayRegion accordingly.
656  region._pixels[2] = int(((1.0f - region._dimensions[3]) * y_size) + 0.5);
657  region._pixels[3] = int(((1.0f - region._dimensions[2]) * y_size) + 0.5);
658  region._pixels_i[2] = int((region._dimensions[3] * y_size) + 0.5);
659  region._pixels_i[3] = int((region._dimensions[2] * y_size) + 0.5);
660 
661  } else {
662  // The window is normal.
663  region._pixels[2] = int((region._dimensions[2] * y_size) + 0.5);
664  region._pixels[3] = int((region._dimensions[3] * y_size) + 0.5);
665  region._pixels_i[2] = int(((1.0f - region._dimensions[2]) * y_size) + 0.5);
666  region._pixels_i[3] = int(((1.0f - region._dimensions[3]) * y_size) + 0.5);
667  }
668 }
669 
670 /**
671  * This is called by GraphicsOutput to indicate that the index of this
672  * DisplayRegion within the window's list of active DisplayRegions might have
673  * changed. The index number will be -1 if the DisplayRegion is not active.
674  *
675  * This is primarily intended only for updating the PStatCollector name
676  * appropriately.
677  */
678 void DisplayRegion::
679 set_active_index(int index) {
680 #if defined(DO_PSTATS) || !defined(NDEBUG)
681  std::ostringstream strm;
682 
683  // To make a more useful name for PStats and debug output, we add the scene
684  // graph name and camera name.
685  NodePath camera = get_camera();
686  if (!camera.is_empty()) {
687  Camera *camera_node = DCAST(Camera, camera.node());
688  if (camera_node != nullptr) {
689  NodePath scene_root = camera_node->get_scene();
690  if (scene_root.is_empty()) {
691  scene_root = camera.get_top();
692  }
693  strm << scene_root.get_name();
694  }
695  }
696 
697  // And add the index in case we have two scene graphs with the same name.
698  strm << "#" << index;
699 
700  _debug_name = strm.str();
701 #endif
702 
703 #ifdef DO_PSTATS
704  _cull_region_pcollector = PStatCollector(_window->get_cull_window_pcollector(), _debug_name);
705  _draw_region_pcollector = PStatCollector(_window->get_draw_window_pcollector(), _debug_name);
706 #endif // DO_PSTATS
707 }
708 
709 /**
710  * Performs a cull traversal. The default implementation simply calls
711  * GraphicsEngine::do_cull.
712  */
713 void DisplayRegion::
714 do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
715  GraphicsStateGuardian *gsg, Thread *current_thread) {
716 
717  GraphicsEngine::do_cull(cull_handler, scene_setup, gsg, current_thread);
718 }
719 
720 /**
721  *
722  */
723 DisplayRegion::CData::
724 CData() :
725  _lens_index(0),
726  _camera_node(nullptr),
727  _active(true),
728  _sort(0),
729  _stereo_channel(Lens::SC_mono),
730  _tex_view_offset(0),
731  _target_tex_page(-1),
732  _scissor_enabled(true)
733 {
734  _regions.push_back(Region());
735 }
736 
737 /**
738  *
739  */
740 DisplayRegion::CData::
741 CData(const DisplayRegion::CData &copy) :
742  _regions(copy._regions),
743  _lens_index(copy._lens_index),
744  _camera(copy._camera),
745  _camera_node(copy._camera_node),
746  _active(copy._active),
747  _sort(copy._sort),
748  _stereo_channel(copy._stereo_channel),
749  _tex_view_offset(copy._tex_view_offset),
750  _target_tex_page(copy._target_tex_page),
751  _scissor_enabled(copy._scissor_enabled)
752 {
753 }
754 
755 /**
756  *
757  */
758 CycleData *DisplayRegion::CData::
759 make_copy() const {
760  return new CData(*this);
761 }
762 
763 /**
764  *
765  */
766 CycleData *DisplayRegion::CDataCull::
767 make_copy() const {
768  return new CDataCull(*this);
769 }
770 
771 /**
772  * Returns the GraphicsPipe that this DisplayRegion is ultimately associated
773  * with, or NULL if no pipe is associated.
774  */
776 get_pipe() const {
777  return (_object->_window != nullptr) ? _object->_window->get_pipe() : nullptr;
778 }
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
RenderBuffer get_render_buffer(int buffer_type, const FrameBufferProperties &prop)
Returns a RenderBuffer object suitable for operating on the requested set of buffers.
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
void cleanup()
Cleans up some pointers associated with the DisplayRegion to help reduce the chance of memory leaks d...
virtual bool framebuffer_copy_to_ram(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)
Copy the pixels within the indicated display region from the framebuffer into system memory,...
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
set_cull_traverser
Specifies the CullTraverser that will be used to draw the contents of this DisplayRegion.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
Definition: pnmImage.h:58
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
static void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup, GraphicsStateGuardian *gsg, Thread *current_thread)
Fires off a cull traversal using the indicated camera.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool get_screenshot(PNMImage &image)
Captures the most-recently rendered image from the framebuffer into the indicated PNMImage.
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:47
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
void compute_pixels_all_stages()
Computes the pixel locations of the DisplayRegion within its window.
bool write(const Filename &filename, PNMFileType *type=nullptr) const
Writes the image to the indicated filename.
Definition: pnmImage.cxx:385
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
is_stereo
Returns true if this is a StereoDisplayRegion, false otherwise.
Definition: displayRegion.h:90
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void compute_pixels()
Computes the pixel locations of the DisplayRegion within its window.
int get_fb_y_size() const
Returns the internal height of the window or buffer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame.
get_pipeline_stage
Returns the Pipeline stage number associated with this thread.
Definition: thread.h:105
static Filename make_screenshot_filename(const std::string &prefix="screenshot")
Synthesizes a suitable default filename for passing to save_screenshot().
PT(Texture) DisplayRegion
Captures the most-recently rendered image from the framebuffer and returns it as a Texture,...
get_engine
Returns the graphics engine that created this output.
set_stereo_channel
Specifies whether the DisplayRegion represents the left or right channel of a stereo pair,...
PStatCollector & get_draw_window_pcollector()
Returns a PStatCollector for timing the draw operation for just this GraphicsOutput.
set_incomplete_render
Sets the incomplete_render flag.
A lightweight class that represents a single element that may be timed and/or counted via stats.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
virtual bool supports_pixel_zoom() const
Returns true if a call to set_pixel_zoom() will be respected, false if it will be ignored.
CullResult * get_cull_result(Thread *current_thread) const
Returns the CullResult value that was stored on this DisplayRegion, presumably by the last successful...
set_tex_view_offset
Sets the current texture view offset for this DisplayRegion.
This defines the abstract interface for an object that receives Geoms identified by the CullTraverser...
Definition: cullHandler.h:28
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
Definition: clockObject.h:94
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
get_name
Returns the name of the referenced node.
Definition: nodePath.h:946
get_camera
Returns the camera associated with this DisplayRegion, or an empty NodePath if no camera is associate...
Definition: displayRegion.h:94
get_pipe
Returns the GraphicsPipe that this window is associated with.
virtual bool supports_pixel_zoom() const
Returns true if a call to set_pixel_zoom() will be respected, false if it will be ignored.
bool get_clear_color_active() const
Returns the current setting of the flag that indicates whether the color buffer should be cleared eve...
bool save_screenshot(const Filename &filename, const std::string &image_comment="")
Saves a screenshot of the region to the indicated filename.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
bool get_clear_depth_active() const
Returns the current setting of the flag that indicates whether the depth buffer should be cleared eve...
get_scene
Returns the scene that will be rendered by the camera.
Definition: camera.h:54
int get_screenshot_buffer_type() const
Returns the RenderBuffer that should be used for capturing screenshots from this particular DrawableR...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
set_texture_reload_priority
Specifies an integer priority which is assigned to any asynchronous texture reload requests spawned w...
int get_draw_stage() const
Returns the pipeline stage from which the draw thread should access data.
This is a base class for the various different classes that represent the result of a frame of render...
int get_draw_buffer_type() const
Returns the RenderBuffer into which the GSG should issue draw commands.
set_target_tex_page
This is a special parameter that is only used when rendering the faces of a cube map or multipage and...
get_inverted
Returns the current setting of the inverted flag.
set_camera
Sets the camera that is associated with this DisplayRegion.
Definition: displayRegion.h:94
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins,...
Definition: cullResult.h:44
int get_fb_x_size() const
Returns the internal width of the window or buffer.
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
A thread; that is, a lightweight process.
Definition: thread.h:46
Encapsulates all the communication with a particular instance of a given rendering backend.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath get_top(Thread *current_thread=Thread::get_current_thread()) const
Returns a singleton NodePath that represents the top of the path, or empty NodePath if this path is e...
Definition: nodePath.cxx:209
set_lens_index
Sets the lens index, allows for multiple lenses to be attached to a camera.
Filename save_screenshot_default(const std::string &prefix="screenshot")
Saves a screenshot of the region to a default filename, and returns the filename, or empty string if ...
set_active
Sets the active flag associated with the DisplayRegion.
Definition: displayRegion.h:98
This class is the main interface to controlling the render process.
PStatCollector & get_cull_window_pcollector()
Returns a PStatCollector for timing the cull operation for just this GraphicsOutput.
bool has_size() const
Returns true if the size of the window/frame buffer is known, false otherwise.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
set_dimensions
Changes the portion of the framebuffer this DisplayRegion corresponds to.
Definition: displayRegion.h:83
set_comment
Writes a user comment string to the image (header).
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer,...
Definition: renderBuffer.h:27
get_gsg
Returns the GSG that is associated with this window.
virtual bool begin_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread before beginning rendering for a given frame.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
set_sort
Sets the sort value associated with the DisplayRegion.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
const GraphicsThreadingModel & get_threading_model() const
Returns the threading model that was used to create this GSG.
GraphicsPipe * get_pipe() const
Returns the GraphicsPipe that this DisplayRegion is ultimately associated with, or NULL if no pipe is...
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.