Panda3D
graphicsOutput.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 graphicsOutput.cxx
10  * @author drose
11  * @date 2004-02-06
12  */
13 
14 #include "graphicsOutput.h"
15 #include "graphicsPipe.h"
16 #include "graphicsEngine.h"
17 #include "graphicsWindow.h"
18 #include "config_display.h"
19 #include "lightMutexHolder.h"
20 #include "renderBuffer.h"
21 #include "indirectLess.h"
22 #include "pStatTimer.h"
23 #include "configVariableBool.h"
24 #include "camera.h"
25 #include "displayRegion.h"
26 #include "lens.h"
27 #include "perspectiveLens.h"
28 #include "pointerTo.h"
29 #include "compassEffect.h"
30 #include "geom.h"
31 #include "geomNode.h"
32 #include "geomTristrips.h"
33 #include "geomVertexWriter.h"
34 #include "throw_event.h"
35 #include "config_gobj.h"
36 
37 using std::string;
38 
39 TypeHandle GraphicsOutput::_type_handle;
40 
41 PStatCollector GraphicsOutput::_make_current_pcollector("Draw:Make current");
42 PStatCollector GraphicsOutput::_copy_texture_pcollector("Draw:Copy texture");
43 PStatCollector GraphicsOutput::_cull_pcollector("Cull");
44 PStatCollector GraphicsOutput::_draw_pcollector("Draw");
45 
46 struct CubeFaceDef {
47  CubeFaceDef(const char *name, const LPoint3 &look_at, const LVector3 &up) :
48  _name(name), _look_at(look_at), _up(up) { }
49 
50  const char *_name;
51  LPoint3 _look_at;
52  LVector3 _up;
53 };
54 
55 static CubeFaceDef cube_faces[6] = {
56  CubeFaceDef("positive_x", LPoint3(1, 0, 0), LVector3(0, -1, 0)),
57  CubeFaceDef("negative_x", LPoint3(-1, 0, 0), LVector3(0, -1, 0)),
58  CubeFaceDef("positive_y", LPoint3(0, 1, 0), LVector3(0, 0, 1)),
59  CubeFaceDef("negative_y", LPoint3(0, -1, 0), LVector3(0, 0, -1)),
60  CubeFaceDef("positive_z", LPoint3(0, 0, 1), LVector3(0, -1, 0)),
61  CubeFaceDef("negative_z", LPoint3(0, 0, -1), LVector3(0, -1, 0))
62 };
63 
64 /**
65  * Normally, the GraphicsOutput constructor is not called directly; these are
66  * created instead via the GraphicsEngine::make_window() function.
67  */
68 GraphicsOutput::
69 GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
70  const string &name,
71  const FrameBufferProperties &fb_prop,
72  const WindowProperties &win_prop,
73  int flags,
75  GraphicsOutput *host,
76  bool default_stereo_flags) :
77  _lock("GraphicsOutput"),
78  _cull_window_pcollector(_cull_pcollector, name),
79  _draw_window_pcollector(_draw_pcollector, name),
80  _clear_window_pcollector(_draw_window_pcollector, "Clear"),
81  _size(0, 0)
82 {
83 #ifdef DO_MEMORY_USAGE
84  MemoryUsage::update_type(this, this);
85 #endif
86  _engine = engine;
87  _pipe = pipe;
88  _gsg = gsg;
89  _host = host;
90  _fb_properties = fb_prop;
91  _name = name;
92  _creation_flags = flags;
93  _has_size = win_prop.has_size();
94  _is_nonzero_size = false;
95  if (_has_size) {
96  _size = win_prop.get_size();
97  _is_nonzero_size = (_size[0] > 0 && _size[1] > 0);
98  }
99  if (_creation_flags & GraphicsPipe::BF_size_track_host) {
100  // If we're tracking the host size, we assume we'll be nonzero eventually.
101  _is_nonzero_size = true;
102  }
103 
104  _is_valid = false;
105  _flip_ready = false;
106  _target_tex_page = -1;
107  _prev_page_dr = nullptr;
108  _sort = 0;
109  _child_sort = 0;
110  _got_child_sort = false;
111  _internal_sort_index = 0;
112  _inverted = window_inverted;
113  _swap_eyes = swap_eyes;
114  _red_blue_stereo = false;
115  _left_eye_color_mask = 0x0f;
116  _right_eye_color_mask = 0x0f;
117  _side_by_side_stereo = false;
118  _sbs_left_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
119  _sbs_right_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
120  _delete_flag = false;
121 
122  if (_fb_properties.is_single_buffered()) {
123  _draw_buffer_type = RenderBuffer::T_front;
124  } else {
125  _draw_buffer_type = RenderBuffer::T_back;
126  }
127 
128  if (default_stereo_flags) {
129  // Check the config variables to see if we should make this a "stereo"
130  // buffer or window.
131  _red_blue_stereo = red_blue_stereo && !fb_prop.is_stereo();
132  if (_red_blue_stereo) {
133  _left_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(0));
134  _right_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(1));
135  }
136  _side_by_side_stereo = side_by_side_stereo && !fb_prop.is_stereo();
137  if (_side_by_side_stereo) {
138  _sbs_left_dimensions.set(sbs_left_dimensions[0], sbs_left_dimensions[1],
139  sbs_left_dimensions[2], sbs_left_dimensions[3]);
140  _sbs_right_dimensions.set(sbs_right_dimensions[0], sbs_right_dimensions[1],
141  sbs_right_dimensions[2], sbs_right_dimensions[3]);
142  }
143  }
144 
145  // We start out with one DisplayRegion that covers the whole window, which
146  // we may use internally for full-window operations like clear() and
147  // get_screenshot().
148  _overlay_display_region = make_mono_display_region(0.0f, 1.0f, 0.0f, 1.0f);
149  _overlay_display_region->set_active(false);
150  _overlay_display_region->set_scissor_enabled(false);
151 
152  // Make sure the "active" flag is set true for pipeline stage 0.
153  {
154  CDWriter cdata(_cycler, true);
155  cdata->_active = true;
156  }
157 
158  // By default, each new GraphicsOutput is set up to clear color and depth.
159  set_clear_color_active(true);
160  set_clear_depth_active(true);
161  set_clear_stencil_active(true);
162  set_clear_color(background_color.get_value());
163 }
164 
165 /**
166  *
167  */
168 GraphicsOutput::
169 ~GraphicsOutput() {
170  // The window should be closed by the time we destruct.
171  nassertv(!is_valid());
172 
173  // We shouldn't have a GraphicsPipe pointer anymore.
174  nassertv(_pipe == nullptr);
175 
176  // We don't have to destruct our child display regions explicitly, since
177  // they are all reference-counted and will go away when their pointers do.
178  // However, we do need to zero out their pointers to us.
179  TotalDisplayRegions::iterator dri;
180  for (dri = _total_display_regions.begin();
181  dri != _total_display_regions.end();
182  ++dri) {
183  (*dri)->_window = nullptr;
184  }
185 
186  _total_display_regions.clear();
187  _overlay_display_region = nullptr;
188 }
189 
190 /**
191  * If the GraphicsOutput is currently rendering to a texture, then all
192  * textures are dissociated from the GraphicsOuput.
193  */
196  CDWriter cdata(_cycler, true);
197  cdata->_textures.clear();
198  ++(cdata->_textures_seq);
199  throw_event("render-texture-targets-changed");
200 }
201 
202 /**
203  * Creates a new Texture object, suitable for rendering the contents of this
204  * buffer into, and appends it to the list of render textures.
205  *
206  * If tex is not NULL, it is the texture that will be set up for rendering
207  * into; otherwise, a new Texture object will be created, in which case you
208  * may call get_texture() to retrieve the new texture pointer.
209  *
210  * You can specify a bitplane to attach the texture to. the legal choices
211  * are:
212  *
213  * - RTP_depth
214  * - RTP_depth_stencil
215  * - RTP_color
216  * - RTP_aux_rgba_0
217  * - RTP_aux_rgba_1
218  * - RTP_aux_rgba_2
219  * - RTP_aux_rgba_3
220  *
221  * If you do not specify a bitplane to attach the texture to, this routine
222  * will use a default based on the texture's format:
223  *
224  * - F_depth_component attaches to RTP_depth
225  * - F_depth_stencil attaches to RTP_depth_stencil
226  * - all other formats attach to RTP_color.
227  *
228  * The texture's format will be changed to match the format of the bitplane to
229  * which it is attached. For example, if you pass in an F_rgba texture and
230  * order that it be attached to RTP_depth_stencil, it will turn into an
231  * F_depth_stencil texture.
232  *
233  * Also see make_texture_buffer(), which is a higher-level interface for
234  * preparing render-to-a-texture mode.
235  */
237 add_render_texture(Texture *tex, RenderTextureMode mode,
238  RenderTexturePlane plane) {
239 
240  if (mode == RTM_none) {
241  return;
242  }
243  LightMutexHolder holder(_lock);
244 
245  // Create texture if necessary.
246  if (tex == nullptr) {
247  tex = new Texture(get_name());
248  tex->set_wrap_u(SamplerState::WM_clamp);
249  tex->set_wrap_v(SamplerState::WM_clamp);
250  } else {
251  tex->clear_ram_image();
252  }
253 
254  // Set it to have no compression by default. You can restore compression
255  // later if you really, really want it; but this freaks out some drivers,
256  // and presumably it's a mistake if you have compression enabled for a
257  // rendered texture.
258  tex->set_compression(Texture::CM_off);
259 
260  // Choose a default bitplane.
261  if (plane == RTP_COUNT) {
262  switch (tex->get_format()) {
263  case Texture::F_depth_stencil:
264  plane = RTP_depth_stencil;
265  break;
266 
267  case Texture::F_depth_component:
268  case Texture::F_depth_component16:
269  case Texture::F_depth_component24:
270  case Texture::F_depth_component32:
271  plane = RTP_depth;
272  break;
273 
274  default:
275  plane = RTP_color;
276  break;
277  }
278  }
279 
280  // Set the texture's format to match the bitplane. (And validate the
281  // bitplane, while we're at it).
282 
283  if (plane == RTP_depth) {
284  _fb_properties.setup_depth_texture(tex);
285  tex->set_match_framebuffer_format(true);
286 
287  } else if (plane == RTP_depth_stencil) {
288  tex->set_format(Texture::F_depth_stencil);
289  if (_fb_properties.get_float_depth()) {
290  tex->set_component_type(Texture::T_float);
291  } else {
292  tex->set_component_type(Texture::T_unsigned_int_24_8);
293  }
294  tex->set_match_framebuffer_format(true);
295 
296  } else if (plane == RTP_color ||
297  plane == RTP_aux_rgba_0 ||
298  plane == RTP_aux_rgba_1 ||
299  plane == RTP_aux_rgba_2 ||
300  plane == RTP_aux_rgba_3) {
301  _fb_properties.setup_color_texture(tex);
302  tex->set_match_framebuffer_format(true);
303 
304  } else if (plane == RTP_aux_hrgba_0 ||
305  plane == RTP_aux_hrgba_1 ||
306  plane == RTP_aux_hrgba_2 ||
307  plane == RTP_aux_hrgba_3) {
308  tex->set_format(Texture::F_rgba16);
309  tex->set_match_framebuffer_format(true);
310 
311  } else if (plane == RTP_aux_float_0 ||
312  plane == RTP_aux_float_1 ||
313  plane == RTP_aux_float_2 ||
314  plane == RTP_aux_float_3) {
315  tex->set_format(Texture::F_rgba32);
316  tex->set_component_type(Texture::T_float);
317  tex->set_match_framebuffer_format(true);
318 
319  } else {
320  display_cat.error() <<
321  "add_render_texture: invalid bitplane specified.\n";
322  return;
323  }
324 
325  // Go ahead and tell the texture our anticipated size, even if it might be
326  // inaccurate (particularly if this is a GraphicsWindow, which has system-
327  // imposed restrictions on size).
328  tex->set_size_padded(get_x_size(), get_y_size(), tex->get_z_size());
329 
330  if (_fb_properties.is_stereo() && plane == RTP_color) {
331  if (tex->get_num_views() < 2) {
332  tex->set_num_views(2);
333  }
334  }
335 
336  if (!support_render_texture || !get_supports_render_texture()) {
337  // Binding is not supported or it is disabled, so just fall back to copy
338  // instead.
339  if (mode == RTM_bind_or_copy) {
340  mode = RTM_copy_texture;
341  } else if (mode == RTM_bind_layered) {
342  // We can't fallback to copy, because that doesn't work for layered
343  // textures. The best thing we can do is raise an error message.
344  display_cat.error() <<
345  "add_render_texture: RTM_bind_layered was requested but "
346  "render-to-texture is not supported or has been disabled!\n";
347  }
348  }
349 
350  if (mode == RTM_bind_layered && _gsg != nullptr && !_gsg->get_supports_geometry_shaders()) {
351  // Layered FBOs require a geometry shader to write to any but the first
352  // layer.
353  display_cat.warning() <<
354  "add_render_texture: RTM_bind_layered was requested but "
355  "geometry shaders are not supported!\n";
356  }
357 
358  if (mode == RTM_bind_or_copy || mode == RTM_bind_layered) {
359  // If we're still planning on binding, indicate it in texture properly.
360  tex->set_render_to_texture(true);
361  }
362 
363  CDWriter cdata(_cycler, true);
364  RenderTexture result;
365  result._texture = tex;
366  result._plane = plane;
367  result._rtm_mode = mode;
368  cdata->_textures.push_back(result);
369  ++(cdata->_textures_seq);
370 
371  throw_event("render-texture-targets-changed");
372 }
373 
374 /**
375  * This is a deprecated interface that made sense back when GraphicsOutputs
376  * could only render into one texture at a time. From now on, use
377  * clear_render_textures and add_render_texture instead.
378  *
379  * @deprecated Use add_render_texture() instead.
380  */
382 setup_render_texture(Texture *tex, bool allow_bind, bool to_ram) {
383  display_cat.warning() <<
384  "Using deprecated setup_render_texture interface.\n";
386  if (to_ram) {
387  add_render_texture(tex, RTM_copy_ram);
388  } else if (allow_bind) {
389  add_render_texture(tex, RTM_bind_or_copy);
390  } else {
391  add_render_texture(tex, RTM_copy_texture);
392  }
393 }
394 
395 /**
396  * Sets the active flag associated with the GraphicsOutput. If the
397  * GraphicsOutput is marked inactive, nothing is rendered.
398  */
399 void GraphicsOutput::
400 set_active(bool active) {
401  CDLockedReader cdata(_cycler);
402  if (cdata->_active != active) {
403  CDWriter cdataw(((GraphicsOutput *)this)->_cycler, cdata, true);
404  cdataw->_active = active;
405  }
406 }
407 
408 /**
409  * Returns true if the window is ready to be rendered into, false otherwise.
410  */
411 bool GraphicsOutput::
412 is_active() const {
413  if (!is_valid()) {
414  return false;
415  }
416 
417  CDLockedReader cdata(_cycler);
418  if (!cdata->_active) {
419  return false;
420  }
421 
422  if (cdata->_one_shot_frame != -1) {
423  // If one_shot is in effect, then we are active only for the one indicated
424  // frame.
425  if (cdata->_one_shot_frame != ClockObject::get_global_clock()->get_frame_count()) {
426  return false;
427  } else {
428  return true;
429  }
430  }
431 
432  // If the window has a clear value set, it is active.
433  if (is_any_clear_active()) {
434  return true;
435  }
436 
437  // If we triggered a copy operation, it is also active.
438  if (_trigger_copy) {
439  return true;
440  }
441 
442  // The window is active if at least one display region is active.
443  if (cdata->_active_display_regions_stale) {
444  CDWriter cdataw(((GraphicsOutput *)this)->_cycler, cdata, false);
445  ((GraphicsOutput *)this)->do_determine_display_regions(cdataw);
446  return !cdataw->_active_display_regions.empty();
447  } else {
448  return !cdata->_active_display_regions.empty();
449  }
450 }
451 
452 /**
453  * Changes the current setting of the one-shot flag. When this is true, the
454  * GraphicsOutput will render the current frame and then automatically set
455  * itself inactive. This is particularly useful for buffers that are created
456  * for the purposes of render-to-texture, for static textures that don't need
457  * to be continually re-rendered once they have been rendered the first time.
458  *
459  * Setting the buffer inactive is not the same thing as destroying it. You
460  * are still responsible for passing this buffer to
461  * GraphicsEngine::remove_window() when you no longer need the texture, in
462  * order to clean up fully. (However, you should not call remove_window() on
463  * this buffer while the texture is still needed, because depending on the
464  * render-to-texture mechanism in use, this may invalidate the texture
465  * contents.)
466  */
467 void GraphicsOutput::
468 set_one_shot(bool one_shot) {
469  CDWriter cdata(_cycler, true);
470  if (one_shot) {
471  cdata->_one_shot_frame = ClockObject::get_global_clock()->get_frame_count();
472  } else {
473  cdata->_one_shot_frame = -1;
474  }
475 }
476 
477 /**
478  * Returns the current setting of the one-shot flag. When this is true, the
479  * GraphicsOutput will automatically set itself inactive after the next frame.
480  */
481 bool GraphicsOutput::
482 get_one_shot() const {
483  CDReader cdata(_cycler);
484  return (cdata->_one_shot_frame == ClockObject::get_global_clock()->get_frame_count());
485 }
486 
487 /**
488  * Changes the current setting of the inverted flag. When this is true, the
489  * scene is rendered into the window upside-down and backwards, that is,
490  * inverted as if viewed through a mirror placed on the floor.
491  *
492  * This is primarily intended to support DirectX (and a few buggy OpenGL
493  * graphics drivers) that perform a framebuffer-to-texture copy upside-down
494  * from the usual OpenGL (and Panda) convention. Panda will automatically set
495  * this flag for offscreen buffers on hardware that is known to do this, to
496  * compensate when rendering offscreen into a texture.
497  */
498 void GraphicsOutput::
499 set_inverted(bool inverted) {
500  if (_inverted != inverted) {
501  _inverted = inverted;
502 
503  if (get_y_size() != 0) {
504  // All of our DisplayRegions need to recompute their pixel positions
505  // now.
506  TotalDisplayRegions::iterator dri;
507  for (dri = _total_display_regions.begin();
508  dri != _total_display_regions.end();
509  ++dri) {
510  (*dri)->compute_pixels(get_x_size(), get_y_size());
511  }
512  }
513  }
514 }
515 
516 /**
517  * Enables side-by-side stereo mode on this particular window. When side-by-
518  * side stereo mode is in effect, DisplayRegions that have the "left" channel
519  * set will render on the part of the window specified by sbs_left_dimensions
520  * (typically the left half: (0, 0.5, 0, 1)), while DisplayRegions that have
521  * the "right" channel set will render on the part of the window specified by
522  * sbs_right_dimensions (typically the right half: (0.5, 1, 0, 1)).
523  *
524  * This is commonly used in a dual-monitor mode, where a window is opened that
525  * spans two monitors, and each monitor represents a different eye.
526  */
528 set_side_by_side_stereo(bool side_by_side_stereo) {
529  LVecBase4 left, right;
530  left.set(sbs_left_dimensions[0], sbs_left_dimensions[1],
531  sbs_left_dimensions[2], sbs_left_dimensions[3]);
532  right.set(sbs_right_dimensions[0], sbs_right_dimensions[1],
533  sbs_right_dimensions[2], sbs_right_dimensions[3]);
534  set_side_by_side_stereo(side_by_side_stereo, left, right);
535 }
536 
537 /**
538  * Enables side-by-side stereo mode on this particular window. When side-by-
539  * side stereo mode is in effect, DisplayRegions that have the "left" channel
540  * set will render on the part of the window specified by sbs_left_dimensions
541  * (typically the left half: (0, 0.5, 0, 1)), while DisplayRegions that have
542  * the "right" channel set will render on the part of the window specified by
543  * sbs_right_dimensions (typically the right half: (0.5, 1, 0, 1)).
544  *
545  * This is commonly used in a dual-monitor mode, where a window is opened that
546  * spans two monitors, and each monitor represents a different eye.
547  */
549 set_side_by_side_stereo(bool side_by_side_stereo,
550  const LVecBase4 &sbs_left_dimensions,
551  const LVecBase4 &sbs_right_dimensions) {
552  _side_by_side_stereo = side_by_side_stereo;
553  if (_side_by_side_stereo) {
554  _sbs_left_dimensions = sbs_left_dimensions;
555  _sbs_right_dimensions = sbs_right_dimensions;
556  } else {
557  _sbs_left_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
558  _sbs_right_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
559  }
560 }
561 
562 /**
563  * Returns the current setting of the delete flag. When this is true, the
564  * GraphicsOutput will automatically be removed before the beginning of the
565  * next frame by the GraphicsEngine.
566  */
568 get_delete_flag() const {
569  // We only delete the window or buffer automatically when it is no longer
570  // associated with a texture.
571  for (int i = 0; i < (int)_hold_textures.size(); i++) {
572  if (_hold_textures[i].is_valid_pointer()) {
573  return false;
574  }
575  }
576 
577  return _delete_flag;
578 }
579 
580 /**
581  * Adjusts the sorting order of this particular GraphicsOutput, relative to
582  * other GraphicsOutputs.
583  */
584 void GraphicsOutput::
585 set_sort(int sort) {
586  if (_sort != sort) {
587  if (_gsg != nullptr &&
588  _gsg->get_engine() != nullptr) {
589  _gsg->get_engine()->set_window_sort(this, sort);
590  }
591  }
592 }
593 
594 /**
595  * Creates a new DisplayRegion that covers the indicated sub-rectangle within
596  * the window. The range on all parameters is 0..1.
597  *
598  * If is_stereo() is true for this window, and default-stereo-camera is
599  * configured true, this actually makes a StereoDisplayRegion. Call
600  * make_mono_display_region() or make_stereo_display_region() if you want to
601  * insist on one or the other.
602  */
604 make_display_region(const LVecBase4 &dimensions) {
605  if (is_stereo() && default_stereo_camera) {
606  return make_stereo_display_region(dimensions);
607  } else {
608  return make_mono_display_region(dimensions);
609  }
610 }
611 
612 /**
613  * Creates a new DisplayRegion that covers the indicated sub-rectangle within
614  * the window. The range on all parameters is 0..1.
615  *
616  * This generally returns a mono DisplayRegion, even if is_stereo() is true.
617  * However, if side-by-side stereo is enabled, this will return a
618  * StereoDisplayRegion whose two eyes are both set to SC_mono. (This is
619  * necessary because in side-by-side stereo mode, it is necessary to draw even
620  * mono DisplayRegions twice).
621  */
623 make_mono_display_region(const LVecBase4 &dimensions) {
624  if (_side_by_side_stereo) {
626  dr->get_left_eye()->set_stereo_channel(Lens::SC_mono);
627  dr->get_right_eye()->set_stereo_channel(Lens::SC_mono);
628  return dr;
629  }
630 
631  return new DisplayRegion(this, dimensions);
632 }
633 
634 /**
635  * Creates a new DisplayRegion that covers the indicated sub-rectangle within
636  * the window. The range on all parameters is 0..1.
637  *
638  * This always returns a stereo DisplayRegion, even if is_stereo() is false.
639  */
641 make_stereo_display_region(const LVecBase4 &dimensions) {
642  PT(DisplayRegion) left, right;
643 
644  if (_side_by_side_stereo) {
645  // On a side-by-side stereo window, each eye gets the corresponding
646  // dimensions of its own sub-region.
647  PN_stdfloat left_l = _sbs_left_dimensions[0];
648  PN_stdfloat left_b = _sbs_left_dimensions[2];
649  PN_stdfloat left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0];
650  PN_stdfloat left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2];
651  LVecBase4 left_dimensions(dimensions[0] * left_w + left_l,
652  dimensions[1] * left_w + left_l,
653  dimensions[2] * left_h + left_b,
654  dimensions[3] * left_h + left_b);
655  left = new DisplayRegion(this, left_dimensions);
656 
657  PN_stdfloat right_l = _sbs_right_dimensions[0];
658  PN_stdfloat right_b = _sbs_right_dimensions[2];
659  PN_stdfloat right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0];
660  PN_stdfloat right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2];
661  LVecBase4 right_dimensions(dimensions[0] * right_w + right_l,
662  dimensions[1] * right_w + right_l,
663  dimensions[2] * right_h + right_b,
664  dimensions[3] * right_h + right_b);
665  right = new DisplayRegion(this, right_dimensions);
666 
667  if (_swap_eyes) {
668  DisplayRegion *t = left;
669  left = right;
670  right = t;
671  }
672 
673  } else {
674  // Not a side-by-side stereo window; thus, both the left and right eyes
675  // are the same region: the region specified.
676  left = new DisplayRegion(this, dimensions);
677  right = new DisplayRegion(this, dimensions);
678 
679  // In this case, we assume that the two eyes will share the same depth
680  // buffer, which means the right eye should clear the depth buffer by
681  // default.
682  if (get_clear_depth_active()) {
683  right->set_clear_depth_active(true);
684  }
685  if (get_clear_stencil_active()) {
686  right->set_clear_stencil_active(true);
687  }
688  }
689 
690  PT(StereoDisplayRegion) stereo = new StereoDisplayRegion(this, dimensions,
691  left, right);
692 
693  return stereo;
694 }
695 
696 /**
697  * Removes the indicated DisplayRegion from the window, and destructs it if
698  * there are no other references.
699  *
700  * Returns true if the DisplayRegion is found and removed, false if it was not
701  * a part of the window.
702  */
704 remove_display_region(DisplayRegion *display_region) {
705  LightMutexHolder holder(_lock);
706 
707  nassertr(display_region != _overlay_display_region, false);
708 
709  if (display_region->is_stereo()) {
710  StereoDisplayRegion *sdr;
711  DCAST_INTO_R(sdr, display_region, false);
712  do_remove_display_region(sdr->get_left_eye());
713  do_remove_display_region(sdr->get_right_eye());
714  }
715 
716  return do_remove_display_region(display_region);
717 }
718 
719 /**
720  * Removes all display regions from the window, except the default one that is
721  * created with the window.
722  */
725  LightMutexHolder holder(_lock);
726 
727  TotalDisplayRegions::iterator dri;
728  for (dri = _total_display_regions.begin();
729  dri != _total_display_regions.end();
730  ++dri) {
731  DisplayRegion *display_region = (*dri);
732  if (display_region != _overlay_display_region) {
733  // Let's aggressively clean up the display region too.
734  display_region->cleanup();
735  display_region->_window = nullptr;
736  }
737  }
738  _total_display_regions.clear();
739  _total_display_regions.push_back(_overlay_display_region);
740 
741  OPEN_ITERATE_ALL_STAGES(_cycler) {
742  CDStageWriter cdata(_cycler, pipeline_stage);
743  cdata->_active_display_regions_stale = true;
744  }
745  CLOSE_ITERATE_ALL_STAGES(_cycler);
746 }
747 
748 /**
749  * Replaces the special "overlay" DisplayRegion that is created for each
750  * window or buffer. See get_overlay_display_region(). This must be a new
751  * DisplayRegion that has already been created for this window, for instance
752  * via a call to make_mono_display_region(). You are responsible for ensuring
753  * that the new DisplayRegion covers the entire window. The previous overlay
754  * display region is not automatically removed; you must explicitly call
755  * remove_display_region() on it after replacing it with this method, if you
756  * wish it to be removed.
757  *
758  * Normally, there is no reason to change the overlay DisplayRegion, so this
759  * method should be used only in very unusual circumstances.
760  */
762 set_overlay_display_region(DisplayRegion *display_region) {
763  nassertv(display_region->get_window() == this);
764  _overlay_display_region = display_region;
765 }
766 
767 /**
768  * Returns the number of DisplayRegions that have been created within the
769  * window, active or otherwise.
770  */
772 get_num_display_regions() const {
773  LightMutexHolder holder(_lock);
774  return _total_display_regions.size();
775 }
776 
777 /**
778  * Returns the nth DisplayRegion of those that have been created within the
779  * window. This may return NULL if n is out of bounds; particularly likely if
780  * the number of display regions has changed since the last call to
781  * get_num_display_regions().
782  */
783 PT(DisplayRegion) GraphicsOutput::
784 get_display_region(int n) const {
785  determine_display_regions();
786  PT(DisplayRegion) result;
787  {
788  LightMutexHolder holder(_lock);
789  if (n >= 0 && n < (int)_total_display_regions.size()) {
790  result = _total_display_regions[n];
791  } else {
792  result = nullptr;
793  }
794  }
795  return result;
796 }
797 
798 /**
799  * Returns the number of active DisplayRegions that have been created within
800  * the window.
801  */
802 int GraphicsOutput::
803 get_num_active_display_regions() const {
804  determine_display_regions();
805  CDReader cdata(_cycler);
806  return cdata->_active_display_regions.size();
807 }
808 
809 /**
810  * Returns the nth active DisplayRegion of those that have been created within
811  * the window. This may return NULL if n is out of bounds; particularly
812  * likely if the number of display regions has changed since the last call to
813  * get_num_active_display_regions().
814  */
815 PT(DisplayRegion) GraphicsOutput::
816 get_active_display_region(int n) const {
817  determine_display_regions();
818 
819  CDReader cdata(_cycler);
820  if (n >= 0 && n < (int)cdata->_active_display_regions.size()) {
821  return cdata->_active_display_regions[n];
822  }
823  return nullptr;
824 }
825 
826 /**
827  * Creates and returns an offscreen buffer for rendering into, the result of
828  * which will be a texture suitable for applying to geometry within the scene
829  * rendered into this window.
830  *
831  * If tex is not NULL, it is the texture that will be set up for rendering
832  * into; otherwise, a new Texture object will be created. In either case, the
833  * target texture can be retrieved from the return value with
834  * buffer->get_texture() (assuming the return value is not NULL).
835  *
836  * If to_ram is true, the buffer will be set up to download its contents to
837  * the system RAM memory associated with the Texture object, instead of
838  * keeping it strictly within texture memory; this is much slower, but it
839  * allows using the texture with any GSG.
840  *
841  * This will attempt to be smart about maximizing render performance while
842  * minimizing framebuffer waste. It might return a GraphicsBuffer set to
843  * render directly into a texture, if possible; or it might return a
844  * ParasiteBuffer that renders into this window. The return value is NULL if
845  * the buffer could not be created for some reason.
846  *
847  * When you are done using the buffer, you should remove it with a call to
848  * GraphicsEngine::remove_window().
849  */
850 GraphicsOutput *GraphicsOutput::
851 make_texture_buffer(const string &name, int x_size, int y_size,
852  Texture *tex, bool to_ram, FrameBufferProperties *fbp) {
853 
854  FrameBufferProperties props;
855  props.set_rgb_color(1);
856  props.set_color_bits(1);
857  props.set_alpha_bits(1);
858  props.set_depth_bits(1);
859 
860  if (fbp == nullptr) {
861  fbp = &props;
862  }
863 
864  int flags = GraphicsPipe::BF_refuse_window;
865  if (textures_power_2 != ATS_none) {
866  flags |= GraphicsPipe::BF_size_power_2;
867  }
868  if (tex != nullptr &&
869  tex->get_texture_type() == Texture::TT_cube_map) {
870  flags |= GraphicsPipe::BF_size_square;
871  }
872 
873  GraphicsOutput *buffer = get_gsg()->get_engine()->
874  make_output(get_gsg()->get_pipe(),
875  name, get_child_sort(),
876  *fbp, WindowProperties::size(x_size, y_size),
877  flags, get_gsg(), get_host());
878 
879  if (buffer != nullptr) {
880  if (buffer->get_gsg() == nullptr ||
881  buffer->get_gsg()->get_prepared_objects() != get_gsg()->get_prepared_objects()) {
882  // If the newly-created buffer doesn't share texture objects with the
883  // current GSG, then we will have to force the texture copy to go
884  // through RAM.
885  to_ram = true;
886  }
887 
888  buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_bind_or_copy);
889  return buffer;
890  }
891 
892  return nullptr;
893 }
894 
895 /**
896  * This is similar to make_texture_buffer() in that it allocates a separate
897  * buffer suitable for rendering to a texture that can be assigned to geometry
898  * in this window, but in this case, the buffer is set up to render the six
899  * faces of a cube map.
900  *
901  * The buffer is automatically set up with six display regions and six
902  * cameras, each of which are assigned the indicated draw_mask and parented to
903  * the given camera_rig node (which you should then put in your scene to
904  * render the cube map from the appropriate point of view).
905  *
906  * You may take the texture associated with the buffer and apply it to
907  * geometry, particularly with TexGenAttrib::M_world_cube_map also in effect,
908  * to apply a reflection of everything seen by the camera rig.
909  */
911 make_cube_map(const string &name, int size, NodePath &camera_rig,
912  DrawMask camera_mask, bool to_ram, FrameBufferProperties *fbp) {
913  if (!to_ram) {
914  // Check the limits imposed by the GSG. (However, if we're rendering the
915  // texture to RAM only, these limits may be irrelevant.)
917  int max_dimension = gsg->get_max_cube_map_dimension();
918  if (max_dimension == 0 || !gsg->get_supports_cube_map()) {
919  // The GSG doesn't support cube mapping; too bad for you.
920  display_cat.warning()
921  << "Cannot make dynamic cube map; GSG does not support cube maps.\n";
922  return nullptr;
923  }
924  if (max_dimension > 0) {
925  size = std::min(max_dimension, size);
926  }
927  }
928 
929  // Usually, we want the whole camera_rig to keep itself unrotated with
930  // respect to the world coordinate space, so the user can apply
931  // TexGenAttrib::M_world_cube_map to the objects on which the cube map
932  // texture is applied. If for some reason the user doesn't want this
933  // behavior, he can take this effect off again.
934  camera_rig.node()->set_effect(CompassEffect::make(NodePath()));
935 
936  PT(Texture) tex = new Texture(name);
937  tex->setup_cube_map();
938  tex->set_wrap_u(SamplerState::WM_clamp);
939  tex->set_wrap_v(SamplerState::WM_clamp);
940  GraphicsOutput *buffer;
941 
942  buffer = make_texture_buffer(name, size, size, tex, to_ram, fbp);
943 
944  // We don't need to clear the overall buffer; instead, we'll clear each
945  // display region.
946  buffer->set_clear_color_active(false);
947  buffer->set_clear_depth_active(false);
948  buffer->set_clear_stencil_active(false);
949 
950  PT(Lens) lens = new PerspectiveLens(90, 90);
951 
952  for (int i = 0; i < 6; i++) {
953  PT(Camera) camera = new Camera(cube_faces[i]._name);
954  camera->set_lens(lens);
955  camera->set_camera_mask(camera_mask);
956  NodePath camera_np = camera_rig.attach_new_node(camera);
957  camera_np.look_at(cube_faces[i]._look_at, cube_faces[i]._up);
958 
959  DisplayRegion *dr;
960  dr = buffer->make_display_region();
961 
962  dr->set_target_tex_page(i);
963  dr->copy_clear_settings(*this);
964  dr->set_camera(camera_np);
965  }
966 
967  return buffer;
968 }
969 
970 /**
971  * Returns a PandaNode containing a square polygon. The dimensions are
972  * (-1,0,-1) to (1,0,1). The texture coordinates are such that the texture of
973  * this GraphicsOutput is aligned properly to the polygon. The GraphicsOutput
974  * promises to surgically update the Geom inside the PandaNode if necessary to
975  * maintain this invariant.
976  *
977  * Each invocation of this function returns a freshly- allocated PandaNode.
978  * You can therefore safely modify the RenderAttribs of the PandaNode. The
979  * PandaNode is initially textured with the texture of this GraphicOutput.
980  */
983  if (_texture_card == nullptr) {
984  PT(GeomVertexData) vdata = create_texture_card_vdata(get_x_size(), get_y_size());
985  PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
986  strip->set_shade_model(Geom::SM_uniform);
987  strip->add_next_vertices(4);
988  strip->close_primitive();
989  PT(Geom) geom = new Geom(vdata);
990  geom->add_primitive(strip);
991  _texture_card = new GeomNode("texture card");
992  _texture_card->add_geom(geom);
993  }
994 
995  NodePath path("texture card");
996  path.node()->add_child(_texture_card);
997 
998  // The texture card, by default, is textured with the first render-to-
999  // texture output texture. Depth and stencil textures are ignored. The
1000  // user can freely alter the card's texture attrib.
1001  CDReader cdata(_cycler);
1002  RenderTextures::const_iterator ri;
1003  for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1004  Texture *texture = (*ri)._texture;
1005  if ((texture->get_format() != Texture::F_depth_stencil)) {
1006  path.set_texture(texture, 0);
1007  break;
1008  }
1009  }
1010 
1011  return path;
1012 }
1013 
1014 /**
1015  * Will attempt to use the depth buffer of the input graphics_output. The
1016  * buffer sizes must be exactly the same.
1017  */
1019 share_depth_buffer(GraphicsOutput *graphics_output) {
1020  return false;
1021 }
1022 
1023 /**
1024  * Discontinue sharing the depth buffer.
1025  */
1028 }
1029 
1030 /**
1031  * Returns true if this particular GraphicsOutput can render directly into a
1032  * texture, or false if it must always copy-to-texture at the end of each
1033  * frame to achieve this effect.
1034  */
1035 bool GraphicsOutput::
1037  return false;
1038 }
1039 
1040 /**
1041  * Returns true if a frame has been rendered and needs to be flipped, false
1042  * otherwise.
1043  */
1045 flip_ready() const {
1046  return _flip_ready;
1047 }
1048 
1049 /**
1050  * This is normally called only from within make_texture_buffer(). When
1051  * called on a ParasiteBuffer, it returns the host of that buffer; but when
1052  * called on some other buffer, it returns the buffer itself.
1053  */
1055 get_host() {
1056  return this;
1057 }
1058 
1059 /**
1060  * This is called by the GraphicsEngine to request that the window (or
1061  * whatever) open itself or, in general, make itself valid, at the next call
1062  * to process_events().
1063  */
1065 request_open() {
1066 }
1067 
1068 /**
1069  * This is called by the GraphicsEngine to request that the window (or
1070  * whatever) close itself or, in general, make itself invalid, at the next
1071  * call to process_events(). By that time we promise the gsg pointer will be
1072  * cleared.
1073  */
1075 request_close() {
1076 }
1077 
1078 /**
1079  * This is called by the GraphicsEngine to insist that the output be closed
1080  * immediately. This is only called from the window thread.
1081  */
1083 set_close_now() {
1084 }
1085 
1086 /**
1087  * Resets the window framebuffer from its derived children. Does nothing
1088  * here.
1089  */
1091 reset_window(bool swapchain) {
1092  display_cat.info()
1093  << "Resetting " << get_type() << "\n";
1094 }
1095 
1096 /**
1097  * Sets the window's _pipe pointer to NULL; this is generally called only as a
1098  * precursor to deleting the window.
1099  */
1101 clear_pipe() {
1102  _pipe = nullptr;
1103 }
1104 
1105 /**
1106  * Changes the x_size and y_size, then recalculates structures that depend on
1107  * size. The recalculation currently includes: - compute_pixels on all the
1108  * graphics regions. - updating the texture card, if one is present.
1109  */
1111 set_size_and_recalc(int x, int y) {
1112  _size.set(x, y);
1113  _has_size = true;
1114 
1115  _is_nonzero_size = (x > 0 && y > 0);
1116 
1117  int fb_x_size = get_fb_x_size();
1118  int fb_y_size = get_fb_y_size();
1119 
1120  TotalDisplayRegions::iterator dri;
1121  for (dri = _total_display_regions.begin();
1122  dri != _total_display_regions.end();
1123  ++dri) {
1124  (*dri)->compute_pixels_all_stages(fb_x_size, fb_y_size);
1125  }
1126 
1127  if (_texture_card != nullptr && _texture_card->get_num_geoms() > 0) {
1128  _texture_card->modify_geom(0)->set_vertex_data(create_texture_card_vdata(x, y));
1129  }
1130 }
1131 
1132 /**
1133  * Clears the entire framebuffer before rendering, according to the settings
1134  * of get_color_clear_active() and get_depth_clear_active() (inherited from
1135  * DrawableRegion).
1136  *
1137  * This function is called only within the draw thread.
1138  */
1140 clear(Thread *current_thread) {
1141  if (is_any_clear_active()) {
1142  if (display_cat.is_spam()) {
1143  display_cat.spam()
1144  << "clear(): " << get_type() << " "
1145  << get_name() << " " << (void *)this << "\n";
1146  }
1147 
1148  nassertv(_gsg != nullptr);
1149 
1150  DisplayRegionPipelineReader dr_reader(_overlay_display_region, current_thread);
1151  _gsg->prepare_display_region(&dr_reader);
1152  _gsg->clear(this);
1153  }
1154 }
1155 
1156 /**
1157  * This function will be called within the draw thread before beginning
1158  * rendering for a given frame. It should do whatever setup is required, and
1159  * return true if the frame should be rendered, or false if it should be
1160  * skipped.
1161  */
1163 begin_frame(FrameMode mode, Thread *current_thread) {
1164  return false;
1165 }
1166 
1167 /**
1168  * This function will be called within the draw thread after rendering is
1169  * completed for a given frame. It should do whatever finalization is
1170  * required.
1171  */
1173 end_frame(FrameMode mode, Thread *current_thread) {
1174 }
1175 
1176 /**
1177  * Called by the GraphicsEngine when the window is about to change to another
1178  * DisplayRegion. This exists mainly to provide a callback for switching the
1179  * cube map face, if we are rendering to the different faces of a cube map.
1180  */
1183  int new_target_tex_page = new_dr->get_target_tex_page();
1184 
1185  if (new_target_tex_page != -1 && new_target_tex_page != _target_tex_page) {
1186 
1187  if (new_target_tex_page == -1) {
1188  new_target_tex_page = 0;
1189  }
1190  int old_target_tex_page = _target_tex_page;
1191  DisplayRegion *old_page_dr = _prev_page_dr;
1192  _target_tex_page = new_target_tex_page;
1193  _prev_page_dr = new_dr->get_object();
1194 
1195  CDReader cdata(_cycler);
1196  RenderTextures::const_iterator ri;
1197  for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1198  RenderTextureMode rtm_mode = (*ri)._rtm_mode;
1199  RenderTexturePlane plane = (*ri)._plane;
1200  Texture *texture = (*ri)._texture;
1201  if (rtm_mode != RTM_none) {
1202  if (rtm_mode == RTM_bind_or_copy || rtm_mode == RTM_bind_layered) {
1203  // In render-to-texture mode, switch the rendering backend to the
1204  // new page, so that the subsequent frame will be rendered to the
1205  // correct page.
1206  select_target_tex_page(_target_tex_page);
1207 
1208  } else if (old_target_tex_page != -1) {
1209  // In copy-to-texture mode, copy the just-rendered framebuffer to
1210  // the old texture page.
1211 
1212  nassertv(old_page_dr != nullptr);
1213  if (display_cat.is_debug()) {
1214  display_cat.debug()
1215  << "Copying texture for " << get_name() << " at scene change.\n";
1216  display_cat.debug()
1217  << "target_tex_page = " << old_target_tex_page << "\n";
1218  }
1219  RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type(),
1220  get_fb_properties());
1221 
1222  if (plane == RTP_color && _fb_properties.is_stereo()) {
1223  // We've got two texture views to copy.
1224  RenderBuffer left(_gsg, buffer._buffer_type & ~RenderBuffer::T_right);
1225  RenderBuffer right(_gsg, buffer._buffer_type & ~RenderBuffer::T_left);
1226 
1227  if (rtm_mode == RTM_copy_ram) {
1228  _gsg->framebuffer_copy_to_ram(texture, 0, old_target_tex_page,
1229  old_page_dr, left);
1230  _gsg->framebuffer_copy_to_ram(texture, 1, old_target_tex_page,
1231  old_page_dr, right);
1232  } else {
1233  _gsg->framebuffer_copy_to_texture(texture, 0, old_target_tex_page,
1234  old_page_dr, left);
1235  _gsg->framebuffer_copy_to_texture(texture, 1, old_target_tex_page,
1236  old_page_dr, right);
1237  }
1238  } else {
1239  if (rtm_mode == RTM_copy_ram) {
1240  _gsg->framebuffer_copy_to_ram(texture, 0, old_target_tex_page,
1241  old_page_dr, buffer);
1242  } else {
1243  _gsg->framebuffer_copy_to_texture(texture, 0, old_target_tex_page,
1244  old_page_dr, buffer);
1245  }
1246  }
1247  }
1248  }
1249  }
1250  }
1251 }
1252 
1253 /**
1254  * Called internally when the window is in render-to-a-texture mode and we are
1255  * in the process of rendering the six faces of a cube map, or any other
1256  * multi-page texture. This should do whatever needs to be done to switch the
1257  * buffer to the indicated page.
1258  */
1261 }
1262 
1263 /**
1264  * This function will be called within the draw thread after end_frame() has
1265  * been called on all windows, to initiate the exchange of the front and back
1266  * buffers.
1267  *
1268  * This should instruct the window to prepare for the flip at the next video
1269  * sync, but it should not wait.
1270  *
1271  * We have the two separate functions, begin_flip() and end_flip(), to make it
1272  * easier to flip all of the windows at the same time.
1273  */
1275 begin_flip() {
1276 }
1277 
1278 /**
1279  * This function will be called within the draw thread after end_frame() has
1280  * been called on all windows, to initiate the exchange of the front and back
1281  * buffers.
1282  *
1283  * This should instruct the window to prepare for the flip when it is command
1284  * but not actually flip
1285  *
1286  */
1288 ready_flip() {
1289 }
1290 
1291 /**
1292  * This function will be called within the draw thread after begin_flip() has
1293  * been called on all windows, to finish the exchange of the front and back
1294  * buffers.
1295  *
1296  * This should cause the window to wait for the flip, if necessary.
1297  */
1299 end_flip() {
1300  _flip_ready = false;
1301 }
1302 
1303 /**
1304  * Do whatever processing in the window thread is appropriate for this output
1305  * object each frame.
1306  *
1307  * This function is called only within the window thread.
1308  */
1310 process_events() {
1311 }
1312 
1313 /**
1314  * Called internally when the pixel factor changes.
1315  */
1316 void GraphicsOutput::
1317 pixel_factor_changed() {
1318  if (_has_size) {
1320  }
1321 }
1322 
1323 /**
1324  * Set the delete flag, and do the usual cleanup activities associated with
1325  * that.
1326  */
1327 void GraphicsOutput::
1328 prepare_for_deletion() {
1329  CDWriter cdata(_cycler, true);
1330  cdata->_active = false;
1331 
1332  // If we were rendering directly to texture, we can't delete the buffer
1333  // until all the textures are gone too.
1334  RenderTextures::iterator ri;
1335  for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1336  if ((*ri)._rtm_mode == RTM_bind_or_copy || (*ri)._rtm_mode == RTM_bind_layered) {
1337  _hold_textures.push_back((*ri)._texture);
1338  }
1339  }
1340  cdata->_textures.clear();
1341 
1342  _delete_flag = true;
1343 
1344  // We have to be sure to remove all of the display regions immediately, so
1345  // that circular reference counts can be cleared up (each display region
1346  // keeps a pointer to a CullResult, which can hold all sorts of pointers).
1348 }
1349 
1350 /**
1351  * If any textures are marked RTM_bind_or_copy, change them to
1352  * RTM_copy_texture. This does not change textures that are set to
1353  * RTM_bind_layered, as layered framebuffers aren't supported with
1354  * RTM_copy_texture.
1355  */
1356 void GraphicsOutput::
1357 promote_to_copy_texture() {
1358  CDLockedReader cdata(_cycler);
1359  RenderTextures::const_iterator ri;
1360 
1361  bool any_bind = false;
1362  for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1363  if ((*ri)._rtm_mode == RTM_bind_or_copy) {
1364  any_bind = true;
1365  break;
1366  }
1367  }
1368  if (any_bind) {
1369  CDWriter cdataw(((GraphicsOutput *)this)->_cycler, cdata, true);
1370  RenderTextures::iterator ri;
1371  for (ri = cdataw->_textures.begin(); ri != cdataw->_textures.end(); ++ri) {
1372  if ((*ri)._rtm_mode == RTM_bind_or_copy) {
1373  (*ri)._rtm_mode = RTM_copy_texture;
1374  }
1375  }
1376  }
1377 }
1378 
1379 /**
1380  * For all textures marked RTM_copy_texture, RTM_copy_ram,
1381  * RTM_triggered_copy_texture, or RTM_triggered_copy_ram, do the necessary
1382  * copies.
1383  *
1384  * Returns true if all copies are successful, false otherwise.
1385  */
1386 bool GraphicsOutput::
1387 copy_to_textures() {
1388  bool okflag = true;
1389 
1390  CDReader cdata(_cycler);
1391  RenderTextures::const_iterator ri;
1392  for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
1393  RenderTextureMode rtm_mode = (*ri)._rtm_mode;
1394  if ((rtm_mode == RTM_none) || (rtm_mode == RTM_bind_or_copy)) {
1395  continue;
1396  }
1397 
1398  Texture *texture = (*ri)._texture;
1399  PStatTimer timer(_copy_texture_pcollector);
1400 
1401  if ((rtm_mode == RTM_copy_texture)||
1402  (rtm_mode == RTM_copy_ram)||
1403  ((rtm_mode == RTM_triggered_copy_texture)&&(_trigger_copy))||
1404  ((rtm_mode == RTM_triggered_copy_ram)&&(_trigger_copy))) {
1405  if (display_cat.is_debug()) {
1406  display_cat.debug()
1407  << "Copying texture for " << get_name() << " at frame end.\n";
1408  display_cat.debug()
1409  << "target_tex_page = " << _target_tex_page << "\n";
1410  }
1411  RenderTexturePlane plane = (*ri)._plane;
1413  if (plane == RTP_color) {
1414  buffer = _gsg->get_render_buffer(get_draw_buffer_type(),
1415  get_fb_properties());
1416  }
1417 
1418  bool copied = false;
1419  DisplayRegion *dr = _overlay_display_region;
1420  if (_prev_page_dr != nullptr) {
1421  dr = _prev_page_dr;
1422  }
1423 
1424  if (plane == RTP_color && _fb_properties.is_stereo()) {
1425  // We've got two texture views to copy.
1426  RenderBuffer left(_gsg, buffer._buffer_type & ~RenderBuffer::T_right);
1427  RenderBuffer right(_gsg, buffer._buffer_type & ~RenderBuffer::T_left);
1428 
1429  if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
1430  copied = _gsg->framebuffer_copy_to_ram(texture, 0, _target_tex_page,
1431  dr, left);
1432  copied = _gsg->framebuffer_copy_to_ram(texture, 1, _target_tex_page,
1433  dr, right) && copied;
1434  } else {
1435  copied = _gsg->framebuffer_copy_to_texture(texture, 0, _target_tex_page,
1436  dr, left);
1437  copied = _gsg->framebuffer_copy_to_texture(texture, 1, _target_tex_page,
1438  dr, right) && copied;
1439  }
1440  } else {
1441  if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
1442  copied = _gsg->framebuffer_copy_to_ram(texture, 0, _target_tex_page,
1443  dr, buffer);
1444  } else {
1445  copied = _gsg->framebuffer_copy_to_texture(texture, 0, _target_tex_page,
1446  dr, buffer);
1447  }
1448  }
1449  if (!copied) {
1450  okflag = false;
1451  }
1452  }
1453  }
1454  if (_trigger_copy != nullptr) {
1455  _trigger_copy->set_result(nullptr);
1456  _trigger_copy = nullptr;
1457  }
1458 
1459  return okflag;
1460 }
1461 
1462 /**
1463  * Generates a GeomVertexData for a texture card.
1464  */
1465 PT(GeomVertexData) GraphicsOutput::
1466 create_texture_card_vdata(int x, int y) {
1467  PN_stdfloat xhi = 1.0;
1468  PN_stdfloat yhi = 1.0;
1469 
1470  if (Texture::get_textures_power_2() != ATS_none) {
1471  int xru = Texture::up_to_power_2(x);
1472  int yru = Texture::up_to_power_2(y);
1473  xhi = (x * 1.0f) / xru;
1474  yhi = (y * 1.0f) / yru;
1475  }
1476 
1478 
1479  PT(GeomVertexData) vdata = new GeomVertexData
1480  ("card", format, Geom::UH_static);
1481 
1482  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
1483  GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
1484  GeomVertexWriter normal(vdata, InternalName::get_normal());
1485 
1486  vertex.add_data3(LVertex::rfu(-1.0f, 0.0f, 1.0f));
1487  vertex.add_data3(LVertex::rfu(-1.0f, 0.0f, -1.0f));
1488  vertex.add_data3(LVertex::rfu( 1.0f, 0.0f, 1.0f));
1489  vertex.add_data3(LVertex::rfu( 1.0f, 0.0f, -1.0f));
1490 
1491  texcoord.add_data2( 0.0f, yhi);
1492  texcoord.add_data2( 0.0f, 0.0f);
1493  texcoord.add_data2( xhi, yhi);
1494  texcoord.add_data2( xhi, 0.0f);
1495 
1496  normal.add_data3(LVector3::back());
1497  normal.add_data3(LVector3::back());
1498  normal.add_data3(LVector3::back());
1499  normal.add_data3(LVector3::back());
1500 
1501  return vdata;
1502 }
1503 
1504 /**
1505  * Called by the DisplayRegion constructor to add the new DisplayRegion to the
1506  * list.
1507  */
1508 DisplayRegion *GraphicsOutput::
1509 add_display_region(DisplayRegion *display_region) {
1510  LightMutexHolder holder(_lock);
1511  CDWriter cdata(_cycler, true);
1512  cdata->_active_display_regions_stale = true;
1513 
1514  _total_display_regions.push_back(display_region);
1515 
1516  return display_region;
1517 }
1518 
1519 /**
1520  * Internal implementation of remove_display_region. Assumes the lock is
1521  * already held.
1522  */
1523 bool GraphicsOutput::
1524 do_remove_display_region(DisplayRegion *display_region) {
1525  nassertr(display_region != _overlay_display_region, false);
1526 
1527  PT(DisplayRegion) drp = display_region;
1528  TotalDisplayRegions::iterator dri =
1529  find(_total_display_regions.begin(), _total_display_regions.end(), drp);
1530  if (dri != _total_display_regions.end()) {
1531  // Let's aggressively clean up the display region too.
1532  display_region->cleanup();
1533  display_region->_window = nullptr;
1534  _total_display_regions.erase(dri);
1535 
1536  OPEN_ITERATE_ALL_STAGES(_cycler) {
1537  CDStageWriter cdata(_cycler, pipeline_stage);
1538  cdata->_active_display_regions_stale = true;
1539  }
1540  CLOSE_ITERATE_ALL_STAGES(_cycler);
1541  return true;
1542  }
1543 
1544  return false;
1545 }
1546 
1547 /**
1548  * Re-sorts the list of active DisplayRegions within the window.
1549  */
1550 void GraphicsOutput::
1551 do_determine_display_regions(GraphicsOutput::CData *cdata) {
1552  cdata->_active_display_regions_stale = false;
1553 
1554  cdata->_active_display_regions.clear();
1555  cdata->_active_display_regions.reserve(_total_display_regions.size());
1556 
1557  int index = 0;
1558  TotalDisplayRegions::const_iterator dri;
1559  for (dri = _total_display_regions.begin();
1560  dri != _total_display_regions.end();
1561  ++dri) {
1562  DisplayRegion *display_region = (*dri);
1563  if (display_region->is_active()) {
1564  cdata->_active_display_regions.push_back(display_region);
1565  display_region->set_active_index(index);
1566  ++index;
1567  } else {
1568  display_region->set_active_index(-1);
1569  }
1570  }
1571 
1572  std::stable_sort(cdata->_active_display_regions.begin(),
1573  cdata->_active_display_regions.end(),
1575 }
1576 
1577 /**
1578  * Parses one of the keywords in the red-blue-stereo-colors Config.prc
1579  * variable, and returns the corresponding bitmask.
1580  *
1581  * These bitmask values are taken from ColorWriteAttrib.
1582  */
1583 unsigned int GraphicsOutput::
1584 parse_color_mask(const string &word) {
1585  unsigned int result = 0;
1586  vector_string components;
1587  tokenize(word, components, "|");
1588 
1589  vector_string::const_iterator ci;
1590  for (ci = components.begin(); ci != components.end(); ++ci) {
1591  string w = downcase(*ci);
1592  if (w == "red" || w == "r") {
1593  result |= 0x001;
1594 
1595  } else if (w == "green" || w == "g") {
1596  result |= 0x002;
1597 
1598  } else if (w == "blue" || w == "b") {
1599  result |= 0x004;
1600 
1601  } else if (w == "yellow" || w == "y") {
1602  result |= 0x003;
1603 
1604  } else if (w == "magenta" || w == "m") {
1605  result |= 0x005;
1606 
1607  } else if (w == "cyan" || w == "c") {
1608  result |= 0x006;
1609 
1610  } else if (w == "alpha" || w == "a") {
1611  result |= 0x008;
1612 
1613  } else if (w == "off") {
1614 
1615  } else {
1616  display_cat.warning()
1617  << "Invalid color in red-blue-stereo-colors: " << (*ci) << "\n";
1618  }
1619  }
1620 
1621  return result;
1622 }
1623 
1624 /**
1625  *
1626  */
1627 GraphicsOutput::CData::
1628 CData() {
1629  // The default is *not* active, so the entire pipeline stage is initially
1630  // populated with inactive outputs. Pipeline stage 0 is set to active in
1631  // the constructor.
1632  _active = false;
1633  _one_shot_frame = -1;
1634  _active_display_regions_stale = false;
1635 }
1636 
1637 /**
1638  *
1639  */
1640 GraphicsOutput::CData::
1641 CData(const GraphicsOutput::CData &copy) :
1642  _textures(copy._textures),
1643  _active(copy._active),
1644  _one_shot_frame(copy._one_shot_frame),
1645  _active_display_regions(copy._active_display_regions),
1646  _active_display_regions_stale(copy._active_display_regions_stale)
1647 {
1648 }
1649 
1650 /**
1651  *
1652  */
1653 CycleData *GraphicsOutput::CData::
1654 make_copy() const {
1655  return new CData(*this);
1656 }
1657 
1658 /**
1659  *
1660  */
1661 std::ostream &
1662 operator << (std::ostream &out, GraphicsOutput::FrameMode fm) {
1663  switch (fm) {
1664  case GraphicsOutput::FM_render:
1665  return out << "render";
1666  case GraphicsOutput::FM_parasite:
1667  return out << "parasite";
1668  case GraphicsOutput::FM_refresh:
1669  return out << "refresh";
1670  }
1671 
1672  return out << "(**invalid GraphicsOutput::FrameMode(" << (int)fm << ")**)";
1673 }
GeomVertexFormat::get_v3n3t2
static const GeomVertexFormat * get_v3n3t2()
Returns a standard vertex format with a 2-component texture coordinate pair, a 3-component normal,...
Definition: geomVertexFormat.I:278
Geom
A container for geometry primitives.
Definition: geom.h:54
ConfigVariableColor::get_value
const LColor & get_value() const
Returns the variable's value.
Definition: configVariableColor.I:103
Texture::get_z_size
get_z_size
Returns the depth of the texture image in texels.
Definition: texture.h:342
StereoDisplayRegion::get_right_eye
get_right_eye
Returns a pointer to the right DisplayRegion managed by this stereo object.
Definition: stereoDisplayRegion.h:67
LightMutexHolder
Similar to MutexHolder, but for a light mutex.
Definition: lightMutexHolder.h:25
Texture::set_wrap_v
set_wrap_v
This setting determines what happens when the texture is sampled with a V value outside the range 0....
Definition: texture.h:374
FrameBufferProperties
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
Definition: frameBufferProperties.h:26
GraphicsOutput::add_render_texture
void add_render_texture(Texture *tex, RenderTextureMode mode, RenderTexturePlane bitplane=RTP_COUNT)
Creates a new Texture object, suitable for rendering the contents of this buffer into,...
Definition: graphicsOutput.cxx:237
PandaNode::set_effect
void set_effect(const RenderEffect *effect)
Adds the indicated render effect to the scene graph on this node.
Definition: pandaNode.cxx:999
CycleData
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
geomVertexWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
throw_event.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath::look_at
void look_at(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the transform on this NodePath so that it rotates to face the indicated point in space.
Definition: nodePath.I:789
GraphicsOutput::make_mono_display_region
DisplayRegion * make_mono_display_region()
Creates a new DisplayRegion that covers the entire window.
Definition: graphicsOutput.I:541
GraphicsOutput::get_num_display_regions
get_num_display_regions
Returns the number of DisplayRegions that have been created within the window, active or otherwise.
Definition: graphicsOutput.h:218
perspectiveLens.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath::set_texture
void set_texture(Texture *tex, int priority=0)
Adds the indicated texture to the list of textures that will be rendered on the default texture stage...
Definition: nodePath.cxx:2871
GraphicsOutput::set_sort
set_sort
Adjusts the sorting order of this particular GraphicsOutput, relative to other GraphicsOutputs.
Definition: graphicsOutput.h:192
tokenize
void tokenize(const string &str, vector_string &words, const string &delimiters, bool discard_repeated_delimiters)
Chops the source string up into pieces delimited by any of the characters specified in delimiters.
Definition: string_utils.cxx:170
DisplayRegion::cleanup
void cleanup()
Cleans up some pointers associated with the DisplayRegion to help reduce the chance of memory leaks d...
Definition: displayRegion.cxx:69
Texture::get_texture_type
get_texture_type
Returns the overall interpretation of the texture.
Definition: texture.h:357
DrawableRegion::get_clear_stencil_active
bool get_clear_stencil_active() const
Returns the current setting of the flag that indicates whether the color buffer should be cleared eve...
Definition: drawableRegion.I:129
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
config_gobj.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DrawableRegion::set_clear_color_active
void set_clear_color_active(bool clear_color_active)
Toggles the flag that indicates whether the color buffer should be cleared every frame.
Definition: drawableRegion.I:80
GraphicsOutput::is_valid
bool is_valid() const
Returns true if the output is fully created and ready for rendering, false otherwise.
Definition: graphicsOutput.I:280
WindowProperties::get_size
get_size
Returns size in pixels of the useful part of the window, not including decorations.
Definition: windowProperties.h:85
Camera
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
PT
PT(DisplayRegion) GraphicsOutput
Returns the nth DisplayRegion of those that have been created within the window.
Definition: graphicsOutput.cxx:783
GraphicsStateGuardian::get_supports_cube_map
get_supports_cube_map
Returns true if this GSG can render cube map textures.
Definition: graphicsStateGuardian.h:192
Texture::get_textures_power_2
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general.
Definition: texture.I:1863
Texture::get_format
get_format
Returns the format of the texture, which represents both the semantic meaning of the texels and,...
Definition: texture.h:362
GraphicsOutput::get_name
get_name
Returns the name that was passed to the GraphicsOutput constructor.
Definition: graphicsOutput.h:120
Texture::set_match_framebuffer_format
set_match_framebuffer_format
Sets the special flag that, if true, indicates to the GSG that the Texture's format should be chosen ...
Definition: texture.h:581
Texture::up_to_power_2
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
Definition: texture.cxx:1983
GraphicsOutput::set_size_and_recalc
void set_size_and_recalc(int x, int y)
Changes the x_size and y_size, then recalculates structures that depend on size.
Definition: graphicsOutput.cxx:1111
RenderBuffer
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer,...
Definition: renderBuffer.h:27
GraphicsOutput::get_y_size
int get_y_size() const
Returns the visible height of the window or buffer, if it is known.
Definition: graphicsOutput.I:159
GraphicsOutput::flip_ready
virtual bool flip_ready() const
Returns true if a frame has been rendered and needs to be flipped, false otherwise.
Definition: graphicsOutput.cxx:1045
GraphicsOutput::change_scenes
void change_scenes(DisplayRegionPipelineReader *new_dr)
Called by the GraphicsEngine when the window is about to change to another DisplayRegion.
Definition: graphicsOutput.cxx:1182
GraphicsOutput::get_x_size
int get_x_size() const
Returns the visible width of the window or buffer, if it is known.
Definition: graphicsOutput.I:145
GraphicsOutput::set_close_now
virtual void set_close_now()
This is called by the GraphicsEngine to insist that the output be closed immediately.
Definition: graphicsOutput.cxx:1083
DrawableRegion::get_clear_depth_active
bool get_clear_depth_active() const
Returns the current setting of the flag that indicates whether the depth buffer should be cleared eve...
Definition: drawableRegion.I:109
GraphicsOutput::get_fb_x_size
int get_fb_x_size() const
Returns the internal width of the window or buffer.
Definition: graphicsOutput.I:180
ConfigVariableString::get_word
std::string get_word(size_t n) const
Returns the variable's nth value.
Definition: configVariableString.I:151
indirectLess.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsOutput::begin_flip
virtual void begin_flip()
This function will be called within the draw thread after end_frame() has been called on all windows,...
Definition: graphicsOutput.cxx:1275
Texture::set_wrap_u
set_wrap_u
This setting determines what happens when the texture is sampled with a U value outside the range 0....
Definition: texture.h:370
GraphicsOutput::ready_flip
virtual void ready_flip()
This function will be called within the draw thread after end_frame() has been called on all windows,...
Definition: graphicsOutput.cxx:1288
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexWriter::add_data3
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row.
Definition: geomVertexWriter.I:1132
ClockObject::get_global_clock
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
GeomVertexWriter
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
Definition: geomVertexWriter.h:55
graphicsEngine.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FrameBufferProperties::setup_color_texture
bool setup_color_texture(Texture *tex) const
Sets the texture up for render-to-texture matching these framebuffer properties.
Definition: frameBufferProperties.cxx:644
GraphicsOutput::get_one_shot
get_one_shot
Returns the current setting of the one-shot flag.
Definition: graphicsOutput.h:159
DisplayRegion
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:57
compassEffect.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsOutput::make_display_region
DisplayRegion * make_display_region()
Creates a new DisplayRegion that covers the entire window.
Definition: graphicsOutput.I:513
BitMask< uint32_t, 32 >
Texture
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
WindowProperties
A container for the various kinds of properties we might ask to have on a graphics window before we o...
Definition: windowProperties.h:29
DrawableRegion::is_any_clear_active
virtual bool is_any_clear_active() const
Returns true if any of the clear types (so far there are just color or depth) have been set active,...
Definition: drawableRegion.cxx:83
downcase
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
Definition: string_utils.cxx:71
graphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
IndirectLess
An STL function object class, this is intended to be used on any ordered collection of pointers to cl...
Definition: indirectLess.h:25
GraphicsEngine
This class is the main interface to controlling the render process.
Definition: graphicsEngine.h:53
GraphicsOutput::remove_display_region
bool remove_display_region(DisplayRegion *display_region)
Removes the indicated DisplayRegion from the window, and destructs it if there are no other reference...
Definition: graphicsOutput.cxx:704
PStatTimer
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
GraphicsOutput::get_gsg
get_gsg
Returns the GSG that is associated with this window.
Definition: graphicsOutput.h:117
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
GeomNode
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
GraphicsOutput::set_overlay_display_region
void set_overlay_display_region(DisplayRegion *display_region)
Replaces the special "overlay" DisplayRegion that is created for each window or buffer.
Definition: graphicsOutput.cxx:762
MemoryUsage::update_type
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
GraphicsOutput
This is a base class for the various different classes that represent the result of a frame of render...
Definition: graphicsOutput.h:63
GraphicsOutput::clear
virtual void clear(Thread *current_thread)
Clears the entire framebuffer before rendering, according to the settings of get_color_clear_active()...
Definition: graphicsOutput.cxx:1140
FrameBufferProperties::setup_depth_texture
bool setup_depth_texture(Texture *tex) const
Sets the texture up for render-to-texture matching these framebuffer properties.
Definition: frameBufferProperties.cxx:723
DisplayRegion::is_active
is_active
Returns the active flag associated with the DisplayRegion.
Definition: displayRegion.h:98
displayRegion.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
StereoDisplayRegion
This is a special DisplayRegion wrapper that actually includes a pair of DisplayRegions internally: t...
Definition: stereoDisplayRegion.h:32
Texture::clear_ram_image
void clear_ram_image()
Discards the current system-RAM image.
Definition: texture.I:1439
CycleDataWriter
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
Definition: cycleDataWriter.h:34
lightMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsOutput::get_supports_render_texture
get_supports_render_texture
Returns true if this particular GraphicsOutput can render directly into a texture,...
Definition: graphicsOutput.h:249
CycleDataReader
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
Definition: cycleDataReader.h:35
Texture::set_compression
set_compression
Requests that this particular Texture be compressed when it is loaded into texture memory.
Definition: texture.h:405
Texture::set_render_to_texture
set_render_to_texture
Sets a flag on the texture that indicates whether the texture is intended to be used as a direct-rend...
Definition: texture.h:409
PStatCollector
A lightweight class that represents a single element that may be timed and/or counted via stats.
Definition: pStatCollector.h:43
WindowProperties::has_size
has_size
Returns true if the window size has been specified, false otherwise.
Definition: windowProperties.h:85
GeomVertexWriter::add_data2
void add_data2(PN_stdfloat x, PN_stdfloat y)
Sets the write row to a particular 2-component value, and advances the write row.
Definition: geomVertexWriter.I:1100
GraphicsPipe
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
DrawableRegion::set_clear_stencil_active
void set_clear_stencil_active(bool clear_stencil_active)
Toggles the flag that indicates whether the stencil buffer should be cleared every frame.
Definition: drawableRegion.I:120
graphicsWindow.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Lens
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
GraphicsOutput::make_stereo_display_region
StereoDisplayRegion * make_stereo_display_region()
Creates a new DisplayRegion that covers the entire window.
Definition: graphicsOutput.I:565
GraphicsOutput::request_close
virtual void request_close()
This is called by the GraphicsEngine to request that the window (or whatever) close itself or,...
Definition: graphicsOutput.cxx:1075
GraphicsOutput::set_active
set_active
Sets the active flag associated with the GraphicsOutput.
Definition: graphicsOutput.h:155
Texture::get_num_views
get_num_views
Returns the number of "views" in the texture.
Definition: texture.h:346
PerspectiveLens
A perspective-type lens: a normal camera.
Definition: perspectiveLens.h:25
geom.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Texture::set_num_views
set_num_views
Sets the number of "views" within a texture.
Definition: texture.h:346
GraphicsOutput::is_stereo
bool is_stereo() const
Returns Returns true if this window can render stereo DisplayRegions, either through red-blue stereo ...
Definition: graphicsOutput.I:423
GeomVertexFormat
This class defines the physical layout of the vertex data stored within a Geom.
Definition: geomVertexFormat.h:55
DisplayRegion::is_stereo
is_stereo
Returns true if this is a StereoDisplayRegion, false otherwise.
Definition: displayRegion.h:90
camera.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Texture::set_format
set_format
Changes the format value for the texture components.
Definition: texture.h:362
configVariableBool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsOutput::get_fb_properties
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
Definition: graphicsOutput.I:413
CycleDataStageWriter
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
Definition: cycleDataStageWriter.h:31
DrawableRegion::get_renderbuffer_type
static int get_renderbuffer_type(int plane)
Returns the RenderBuffer::Type that corresponds to a RenderTexturePlane.
Definition: drawableRegion.cxx:130
GraphicsOutput::reset_window
virtual void reset_window(bool swapchain)
Resets the window framebuffer from its derived children.
Definition: graphicsOutput.cxx:1091
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
GraphicsOutput::select_target_tex_page
virtual void select_target_tex_page(int page)
Called internally when the window is in render-to-a-texture mode and we are in the process of renderi...
Definition: graphicsOutput.cxx:1260
ClockObject::get_frame_count
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
Definition: clockObject.h:94
DrawableRegion::copy_clear_settings
void copy_clear_settings(const DrawableRegion &copy)
Copies only the clear settings from the other drawable region.
Definition: drawableRegion.I:66
WindowProperties::size
static WindowProperties size(const LVecBase2i &size)
Returns a WindowProperties structure with only the size specified.
Definition: windowProperties.cxx:142
GraphicsOutput::get_host
virtual GraphicsOutput * get_host()
This is normally called only from within make_texture_buffer().
Definition: graphicsOutput.cxx:1055
GraphicsOutput::get_fb_y_size
int get_fb_y_size() const
Returns the internal height of the window or buffer.
Definition: graphicsOutput.I:190
GraphicsOutput::setup_render_texture
void setup_render_texture(Texture *tex, bool allow_bind, bool to_ram)
This is a deprecated interface that made sense back when GraphicsOutputs could only render into one t...
Definition: graphicsOutput.cxx:382
GraphicsOutput::get_delete_flag
bool get_delete_flag() const
Returns the current setting of the delete flag.
Definition: graphicsOutput.cxx:568
GraphicsOutput::set_inverted
set_inverted
Changes the current setting of the inverted flag.
Definition: graphicsOutput.h:163
DisplayRegion::set_target_tex_page
set_target_tex_page
This is a special parameter that is only used when rendering the faces of a cube map or multipage and...
Definition: displayRegion.h:132
GraphicsOutput::set_one_shot
set_one_shot
Changes the current setting of the one-shot flag.
Definition: graphicsOutput.h:159
GraphicsOutput::get_pipe
get_pipe
Returns the GraphicsPipe that this window is associated with.
Definition: graphicsOutput.h:118
DisplayRegion::set_camera
set_camera
Sets the camera that is associated with this DisplayRegion.
Definition: displayRegion.h:94
DrawableRegion::get_draw_buffer_type
int get_draw_buffer_type() const
Returns the RenderBuffer into which the GSG should issue draw commands.
Definition: drawableRegion.I:234
GeomTristrips
Defines a series of triangle strips.
Definition: geomTristrips.h:23
geomTristrips.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath::attach_new_node
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
Definition: nodePath.cxx:563
GraphicsOutput::make_cube_map
GraphicsOutput * make_cube_map(const std::string &name, int size, NodePath &camera_rig, DrawMask camera_mask=PandaNode::get_all_camera_mask(), bool to_ram=false, FrameBufferProperties *fbp=nullptr)
This is similar to make_texture_buffer() in that it allocates a separate buffer suitable for renderin...
Definition: graphicsOutput.cxx:911
GraphicsOutput::request_open
virtual void request_open()
This is called by the GraphicsEngine to request that the window (or whatever) open itself or,...
Definition: graphicsOutput.cxx:1065
GraphicsOutput::remove_all_display_regions
void remove_all_display_regions()
Removes all display regions from the window, except the default one that is created with the window.
Definition: graphicsOutput.cxx:724
GraphicsOutput::is_active
is_active
Returns true if the window is ready to be rendered into, false otherwise.
Definition: graphicsOutput.h:155
GraphicsOutput::end_frame
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.
Definition: graphicsOutput.cxx:1173
DisplayRegion::get_window
get_window
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
Definition: displayRegion.h:88
GraphicsOutput::get_child_sort
get_child_sort
Returns the sort value of future offscreen buffers created by make_texture_sort().
Definition: graphicsOutput.h:197
geomNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
GraphicsOutput::set_side_by_side_stereo
void set_side_by_side_stereo(bool side_by_side_stereo)
Enables side-by-side stereo mode on this particular window.
Definition: graphicsOutput.cxx:528
DrawableRegion::set_clear_depth_active
void set_clear_depth_active(bool clear_depth_active)
Toggles the flag that indicates whether the depth buffer should be cleared every frame.
Definition: drawableRegion.I:100
StereoDisplayRegion::get_left_eye
get_left_eye
Returns a pointer to the left DisplayRegion managed by this stereo object.
Definition: stereoDisplayRegion.h:66
GraphicsOutput::unshare_depth_buffer
virtual void unshare_depth_buffer()
Discontinue sharing the depth buffer.
Definition: graphicsOutput.cxx:1027
GraphicsStateGuardian::get_max_cube_map_dimension
get_max_cube_map_dimension
Returns the largest possible texture size in any one dimension for a cube map texture,...
Definition: graphicsStateGuardian.h:185
GraphicsOutput::process_events
virtual void process_events()
Do whatever processing in the window thread is appropriate for this output object each frame.
Definition: graphicsOutput.cxx:1310
Texture::set_component_type
set_component_type
Changes the data value for the texture components.
Definition: texture.h:366
Texture::set_size_padded
void set_size_padded(int x=1, int y=1, int z=1)
Changes the size of the texture, padding if necessary, and setting the pad region as well.
Definition: texture.cxx:1907
NodePath::node
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
config_display.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsOutput::clear_pipe
virtual void clear_pipe()
Sets the window's _pipe pointer to NULL; this is generally called only as a precursor to deleting the...
Definition: graphicsOutput.cxx:1101
GraphicsOutput::clear_render_textures
void clear_render_textures()
If the GraphicsOutput is currently rendering to a texture, then all textures are dissociated from the...
Definition: graphicsOutput.cxx:195
DisplayRegionPipelineReader::get_target_tex_page
int get_target_tex_page() const
Returns the target page number associated with this particular DisplayRegion, or -1 if it is not asso...
Definition: displayRegion.I:759
GraphicsOutput::end_flip
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
Definition: graphicsOutput.cxx:1299
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
GraphicsOutput::get_texture_card
NodePath get_texture_card()
Returns a PandaNode containing a square polygon.
Definition: graphicsOutput.cxx:982
DisplayRegionPipelineReader
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
Definition: displayRegion.h:311
pointerTo.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FrameBufferProperties::set_color_bits
set_color_bits
Sets the number of requested color bits as a single number that represents the sum of the individual ...
Definition: frameBufferProperties.h:124
graphicsOutput.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Texture::setup_cube_map
void setup_cube_map()
Sets the texture as an empty cube map texture with no dimensions.
Definition: texture.I:155
GraphicsOutput::share_depth_buffer
virtual bool share_depth_buffer(GraphicsOutput *graphics_output)
Will attempt to use the depth buffer of the input graphics_output.
Definition: graphicsOutput.cxx:1019
GraphicsOutput::begin_frame
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.
Definition: graphicsOutput.cxx:1163
lens.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
renderBuffer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.