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  */
69 cleanup() {
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  */
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  */
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  */
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  */
458 get_screenshot(PNMImage &image) {
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  *
519  */
520 void DisplayRegion::
521 clear_cull_result() {
522  CDCullWriter cdata_cull(_cycler_cull, true);
523  cdata_cull->_cull_result = nullptr;
524 }
525 
526 /**
527  * Returns a special scene graph constructed to represent the results of the
528  * last frame's cull operation.
529  *
530  * This will be a hierarchy of nodes, one node for each bin, each of which
531  * will in term be a parent of a number of GeomNodes, representing the
532  * geometry drawn in each bin.
533  *
534  * This is useful mainly for high-level debugging and abstraction tools; it
535  * should not be mistaken for the low-level cull result itself, which is
536  * constructed and maintained internally. No such scene graph is normally
537  * constructed during the rendering of a frame; this is an artificial
538  * construct created for the purpose of making it easy to analyze the results
539  * of the cull operation.
540  */
541 PT(PandaNode) DisplayRegion::
542 make_cull_result_graph() {
544  if (cull_result == nullptr) {
545  return nullptr;
546  }
547  return cull_result->make_result_graph();
548 }
549 
550 /**
551  * Computes the pixel locations of the DisplayRegion within its window. The
552  * DisplayRegion will request the size from the window.
553  */
555 compute_pixels() {
556  if (_window != nullptr) {
557  CDWriter cdata(_cycler, false);
558  for (size_t i = 0; i < cdata->_regions.size(); ++i) {
559  do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(),
560  cdata);
561  }
562  }
563 }
564 
565 /**
566  * Computes the pixel locations of the DisplayRegion within its window. The
567  * DisplayRegion will request the size from the window.
568  */
571  if (_window != nullptr) {
572  OPEN_ITERATE_ALL_STAGES(_cycler) {
573  CDStageWriter cdata(_cycler, pipeline_stage);
574  for (size_t i = 0; i < cdata->_regions.size(); ++i) {
575  do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(),
576  cdata);
577  }
578  }
579  CLOSE_ITERATE_ALL_STAGES(_cycler);
580  }
581 }
582 
583 /**
584  * Computes the pixel locations of the DisplayRegion within its window, given
585  * the size of the window in pixels.
586  */
588 compute_pixels(int x_size, int y_size) {
589  CDWriter cdata(_cycler, false);
590  for (size_t i = 0; i < cdata->_regions.size(); ++i) {
591  do_compute_pixels(i, x_size, y_size, cdata);
592  }
593 }
594 
595 /**
596  * Performs a compute_pixels() operation for all stages of the pipeline. This
597  * is appropriate, for instance, when a window changes sizes, since this is a
598  * global operation; and you want the new window size to be immediately
599  * available even to the downstream stages.
600  */
602 compute_pixels_all_stages(int x_size, int y_size) {
603  OPEN_ITERATE_ALL_STAGES(_cycler) {
604  CDStageWriter cdata(_cycler, pipeline_stage);
605  for (size_t i = 0; i < cdata->_regions.size(); ++i) {
606  do_compute_pixels(i, x_size, y_size, cdata);
607  }
608  }
609  CLOSE_ITERATE_ALL_STAGES(_cycler);
610 }
611 
612 /**
613  * Returns true if a call to set_pixel_zoom() will be respected, false if it
614  * will be ignored. If this returns false, then get_pixel_factor() will
615  * always return 1.0, regardless of what value you specify for
616  * set_pixel_zoom().
617  *
618  * This may return false if the underlying renderer doesn't support pixel
619  * zooming, or if you have called this on a DisplayRegion that doesn't have
620  * both set_clear_color() and set_clear_depth() enabled.
621  */
623 supports_pixel_zoom() const {
624  if (_window != nullptr) {
625  if (_window->supports_pixel_zoom()) {
627  }
628  }
629  return false;
630 }
631 
632 /**
633  * Intended to be called when the active state on a nested channel or layer or
634  * display region changes, forcing the window to recompute its list of active
635  * display regions. It is assumed the lock is already held.
636  */
637 void DisplayRegion::
638 win_display_regions_changed() {
639  if (_window != nullptr) {
640  _window->win_display_regions_changed();
641  }
642 }
643 
644 /**
645  * The private implementation of compute_pixels, this assumes that we already
646  * have the lock.
647  */
648 void DisplayRegion::
649 do_compute_pixels(int i, int x_size, int y_size, CData *cdata) {
650  if (display_cat.is_debug()) {
651  display_cat.debug()
652  << "DisplayRegion::do_compute_pixels(" << x_size << ", " << y_size << ")\n";
653  }
654 
655  Region &region = cdata->_regions[i];
656 
657  region._pixels[0] = int((region._dimensions[0] * x_size) + 0.5);
658  region._pixels[1] = int((region._dimensions[1] * x_size) + 0.5);
659  region._pixels_i[0] = region._pixels[0];
660  region._pixels_i[1] = region._pixels[1];
661 
662  nassertv(_window != nullptr);
663  if (_window->get_inverted()) {
664  // The window is inverted; compute the DisplayRegion accordingly.
665  region._pixels[2] = int(((1.0f - region._dimensions[3]) * y_size) + 0.5);
666  region._pixels[3] = int(((1.0f - region._dimensions[2]) * y_size) + 0.5);
667  region._pixels_i[2] = int((region._dimensions[3] * y_size) + 0.5);
668  region._pixels_i[3] = int((region._dimensions[2] * y_size) + 0.5);
669 
670  } else {
671  // The window is normal.
672  region._pixels[2] = int((region._dimensions[2] * y_size) + 0.5);
673  region._pixels[3] = int((region._dimensions[3] * y_size) + 0.5);
674  region._pixels_i[2] = int(((1.0f - region._dimensions[2]) * y_size) + 0.5);
675  region._pixels_i[3] = int(((1.0f - region._dimensions[3]) * y_size) + 0.5);
676  }
677 }
678 
679 /**
680  * This is called by GraphicsOutput to indicate that the index of this
681  * DisplayRegion within the window's list of active DisplayRegions might have
682  * changed. The index number will be -1 if the DisplayRegion is not active.
683  *
684  * This is primarily intended only for updating the PStatCollector name
685  * appropriately.
686  */
687 void DisplayRegion::
688 set_active_index(int index) {
689 #if defined(DO_PSTATS) || !defined(NDEBUG)
690  std::ostringstream strm;
691 
692  // To make a more useful name for PStats and debug output, we add the scene
693  // graph name and camera name.
694  NodePath camera = get_camera();
695  if (!camera.is_empty()) {
696  Camera *camera_node = DCAST(Camera, camera.node());
697  if (camera_node != nullptr) {
698  NodePath scene_root = camera_node->get_scene();
699  if (scene_root.is_empty()) {
700  scene_root = camera.get_top();
701  }
702  strm << scene_root.get_name();
703  }
704  }
705 
706  // And add the index in case we have two scene graphs with the same name.
707  strm << "#" << index;
708 
709  _debug_name = strm.str();
710 #endif
711 
712 #ifdef DO_PSTATS
713  _cull_region_pcollector = PStatCollector(_window->get_cull_window_pcollector(), _debug_name);
714  _draw_region_pcollector = PStatCollector(_window->get_draw_window_pcollector(), _debug_name);
715 #endif // DO_PSTATS
716 }
717 
718 /**
719  * Performs a cull traversal. The default implementation simply calls
720  * GraphicsEngine::do_cull.
721  */
722 void DisplayRegion::
723 do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
724  GraphicsStateGuardian *gsg, Thread *current_thread) {
725 
726  GraphicsEngine::do_cull(cull_handler, scene_setup, gsg, current_thread);
727 }
728 
729 /**
730  *
731  */
732 DisplayRegion::CData::
733 CData() :
734  _lens_index(0),
735  _camera_node(nullptr),
736  _active(true),
737  _sort(0),
738  _stereo_channel(Lens::SC_mono),
739  _tex_view_offset(0),
740  _target_tex_page(-1),
741  _scissor_enabled(true)
742 {
743  _regions.push_back(Region());
744 }
745 
746 /**
747  *
748  */
749 DisplayRegion::CData::
750 CData(const DisplayRegion::CData &copy) :
751  _regions(copy._regions),
752  _lens_index(copy._lens_index),
753  _camera(copy._camera),
754  _camera_node(copy._camera_node),
755  _active(copy._active),
756  _sort(copy._sort),
757  _stereo_channel(copy._stereo_channel),
758  _tex_view_offset(copy._tex_view_offset),
759  _target_tex_page(copy._target_tex_page),
760  _scissor_enabled(copy._scissor_enabled)
761 {
762 }
763 
764 /**
765  *
766  */
767 CycleData *DisplayRegion::CData::
768 make_copy() const {
769  return new CData(*this);
770 }
771 
772 /**
773  *
774  */
775 CycleData *DisplayRegion::CDataCull::
776 make_copy() const {
777  return new CDataCull(*this);
778 }
779 
780 /**
781  * Returns the GraphicsPipe that this DisplayRegion is ultimately associated
782  * with, or NULL if no pipe is associated.
783  */
785 get_pipe() const {
786  return (_object->_window != nullptr) ? _object->_window->get_pipe() : nullptr;
787 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
get_scene
Returns the scene that will be rendered by the camera.
Definition: camera.h:54
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
Definition: clockObject.h:94
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
This defines the abstract interface for an object that receives Geoms identified by the CullTraverser...
Definition: cullHandler.h:28
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins,...
Definition: cullResult.h:44
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
GraphicsPipe * get_pipe() const
Returns the GraphicsPipe that this DisplayRegion is ultimately associated with, or NULL if no pipe is...
is_stereo
Returns true if this is a StereoDisplayRegion, false otherwise.
Definition: displayRegion.h:90
get_cull_traverser
Returns the CullTraverser that will be used to draw the contents of this DisplayRegion.
void compute_pixels()
Computes the pixel locations of the DisplayRegion within its window.
bool save_screenshot(const Filename &filename, const std::string &image_comment="")
Saves a screenshot of the region to the indicated filename.
CullResult * get_cull_result(Thread *current_thread) const
Returns the CullResult value that was stored on this DisplayRegion, presumably by the last successful...
set_camera
Sets the camera that is associated with this DisplayRegion.
Definition: displayRegion.h:94
set_tex_view_offset
Sets the current texture view offset for this DisplayRegion.
set_target_tex_page
This is a special parameter that is only used when rendering the faces of a cube map or multipage and...
bool get_screenshot(PNMImage &image)
Captures the most-recently rendered image from the framebuffer into the indicated PNMImage.
get_camera
Returns the camera associated with this DisplayRegion, or an empty NodePath if no camera is associate...
Definition: displayRegion.h:94
set_lens_index
Sets the lens index, allows for multiple lenses to be attached to a camera.
get_window
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
Definition: displayRegion.h:88
void cleanup()
Cleans up some pointers associated with the DisplayRegion to help reduce the chance of memory leaks d...
void compute_pixels_all_stages()
Computes the pixel locations of the DisplayRegion within its window.
get_pipe
Returns the GraphicsPipe that this DisplayRegion is ultimately associated with, or NULL if no pipe is...
Definition: displayRegion.h:89
set_sort
Sets the sort value associated with the DisplayRegion.
static Filename make_screenshot_filename(const std::string &prefix="screenshot")
Synthesizes a suitable default filename for passing to save_screenshot().
set_cull_traverser
Specifies the CullTraverser that will be used to draw the contents of this DisplayRegion.
set_dimensions
Changes the portion of the framebuffer this DisplayRegion corresponds to.
Definition: displayRegion.h:83
set_active
Sets the active flag associated with the DisplayRegion.
Definition: displayRegion.h:98
set_stereo_channel
Specifies whether the DisplayRegion represents the left or right channel of a stereo pair,...
set_texture_reload_priority
Specifies an integer priority which is assigned to any asynchronous texture reload requests spawned w...
virtual bool supports_pixel_zoom() const
Returns true if a call to set_pixel_zoom() will be respected, false if it will be ignored.
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_incomplete_render
Sets the incomplete_render flag.
int get_draw_buffer_type() const
Returns the RenderBuffer into which the GSG should issue draw commands.
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_depth_active() const
Returns the current setting of the flag that indicates whether the depth buffer should be cleared eve...
bool get_clear_color_active() const
Returns the current setting of the flag that indicates whether the color buffer should be cleared eve...
int get_screenshot_buffer_type() const
Returns the RenderBuffer that should be used for capturing screenshots from this particular DrawableR...
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
This class is the main interface to controlling the render process.
static void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup, GraphicsStateGuardian *gsg, Thread *current_thread)
Fires off a cull traversal using the indicated camera.
This is a base class for the various different classes that represent the result of a frame of render...
int get_fb_x_size() const
Returns the internal width of the window or buffer.
get_inverted
Returns the current setting of the inverted flag.
get_pipe
Returns the GraphicsPipe that this window is associated with.
bool has_size() const
Returns true if the size of the window/frame buffer is known, false otherwise.
get_gsg
Returns the GSG that is associated with this window.
PStatCollector & get_draw_window_pcollector()
Returns a PStatCollector for timing the draw operation for just this GraphicsOutput.
PStatCollector & get_cull_window_pcollector()
Returns a PStatCollector for timing the cull operation for just this GraphicsOutput.
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.
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the 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.
int get_fb_y_size() const
Returns the internal height of the window or buffer.
get_engine
Returns the graphics engine that created this output.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
Encapsulates all the communication with a particular instance of a given rendering backend.
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,...
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
RenderBuffer get_render_buffer(int buffer_type, const FrameBufferProperties &prop)
Returns a RenderBuffer object suitable for operating on the requested set of buffers.
const GraphicsThreadingModel & get_threading_model() const
Returns the threading model that was used to create this GSG.
int get_draw_stage() const
Returns the pipeline stage from which the draw thread should access data.
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
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
get_name
Returns the name of the referenced node.
Definition: nodePath.h:945
set_comment
Writes a user comment string to the image (header).
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
bool write(const Filename &filename, PNMFileType *type=nullptr) const
Writes the image to the indicated filename.
Definition: pnmImage.cxx:385
A lightweight class that represents a single element that may be timed and/or counted via stats.
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer,...
Definition: renderBuffer.h:27
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
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
A thread; that is, a lightweight process.
Definition: thread.h:46
get_pipeline_stage
Returns the Pipeline stage number associated with this thread.
Definition: thread.h:105
get_current_pipeline_stage
Returns the integer pipeline stage associated with the current thread.
Definition: thread.h:110
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(Texture) DisplayRegion
Captures the most-recently rendered image from the framebuffer and returns it as a Texture,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.