Panda3D

displayRegion.cxx

00001 // Filename: displayRegion.cxx
00002 // Created by:  cary (10Feb99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "displayRegion.h"
00016 #include "stereoDisplayRegion.h"
00017 #include "graphicsOutput.h"
00018 #include "config_display.h"
00019 #include "texture.h"
00020 #include "camera.h"
00021 #include "dcast.h"
00022 #include "pnmImage.h"
00023 
00024 #include <time.h>
00025 
00026 TypeHandle DisplayRegion::_type_handle;
00027 TypeHandle DisplayRegionPipelineReader::_type_handle;
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: DisplayRegion::Constructor
00031 //       Access: Protected
00032 //  Description:
00033 ////////////////////////////////////////////////////////////////////
00034 DisplayRegion::
00035 DisplayRegion(GraphicsOutput *window, float l, float r, float b, float t) :
00036   _window(window),
00037   _incomplete_render(true),
00038   _texture_reload_priority(0),
00039   _cull_region_pcollector("Cull:Invalid"),
00040   _draw_region_pcollector("Draw:Invalid")
00041 {
00042   _screenshot_buffer_type = window->get_draw_buffer_type();
00043   _draw_buffer_type = window->get_draw_buffer_type();
00044   set_dimensions(l, r, b, t);
00045   compute_pixels_all_stages();
00046 }
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //     Function: DisplayRegion::Copy Constructor
00050 //       Access: Private
00051 //  Description:
00052 ////////////////////////////////////////////////////////////////////
00053 DisplayRegion::
00054 DisplayRegion(const DisplayRegion &copy) : 
00055   _window(NULL),
00056   _cull_region_pcollector("Cull:Invalid"),
00057   _draw_region_pcollector("Draw:Invalid")
00058 {
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: DisplayRegion::Copy Assignment Operator
00063 //       Access: Private
00064 //  Description:
00065 ////////////////////////////////////////////////////////////////////
00066 void DisplayRegion::
00067 operator = (const DisplayRegion&) {
00068   nassertv(false);
00069 }
00070 
00071 ////////////////////////////////////////////////////////////////////
00072 //     Function: DisplayRegion::Destructor
00073 //       Access: Public, Virtual
00074 //  Description:
00075 ////////////////////////////////////////////////////////////////////
00076 DisplayRegion::
00077 ~DisplayRegion() {
00078   cleanup();
00079 
00080   // The window pointer should already have been cleared by the time
00081   // the DisplayRegion destructs (since the GraphicsOutput class keeps
00082   // a reference count on the DisplayRegion).
00083   nassertv(_window == (GraphicsOutput *)NULL);
00084 }
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //     Function: DisplayRegion::cleanup
00088 //       Access: Public
00089 //  Description: Cleans up some pointers associated with the
00090 //               DisplayRegion to help reduce the chance of memory
00091 //               leaks due to circular reference counts.
00092 ////////////////////////////////////////////////////////////////////
00093 void DisplayRegion::
00094 cleanup() {
00095   set_camera(NodePath());
00096 
00097   CDCullWriter cdata(_cycler_cull, true);
00098   cdata->_cull_result = NULL;
00099 }
00100 
00101 ////////////////////////////////////////////////////////////////////
00102 //     Function: DisplayRegion::set_lens_index
00103 //       Access: Published
00104 //  Description: Sets the lens index, allows for multiple lenses to
00105 //               be attached to a camera.  This is useful for a 
00106 //               variety of setups, such as fish eye rendering.
00107 //               The default is 0.
00108 ////////////////////////////////////////////////////////////////////
00109 void DisplayRegion::
00110 set_lens_index(int index) {
00111   int pipeline_stage = Thread::get_current_pipeline_stage();
00112   nassertv(pipeline_stage == 0);
00113   CDWriter cdata(_cycler);
00114   cdata->_lens_index = index;
00115 }
00116 
00117 ////////////////////////////////////////////////////////////////////
00118 //     Function: DisplayRegion::set_dimensions
00119 //       Access: Published, Virtual
00120 //  Description: Changes the portion of the framebuffer this
00121 //               DisplayRegion corresponds to.  The parameters range
00122 //               from 0 to 1, where 0,0 is the lower left corner and
00123 //               1,1 is the upper right; (0, 1, 0, 1) represents the
00124 //               whole screen.
00125 ////////////////////////////////////////////////////////////////////
00126 void DisplayRegion::
00127 set_dimensions(float l, float r, float b, float t) {
00128   int pipeline_stage = Thread::get_current_pipeline_stage();
00129   nassertv(pipeline_stage == 0);
00130   CDWriter cdata(_cycler);
00131 
00132   cdata->_l = l;
00133   cdata->_r = r;
00134   cdata->_b = b;
00135   cdata->_t = t;
00136 
00137   if (_window != (GraphicsOutput *)NULL && _window->has_size()) {
00138     do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), cdata);
00139   }
00140 }
00141 
00142 ////////////////////////////////////////////////////////////////////
00143 //     Function: DisplayRegion::get_pipe
00144 //       Access: Published
00145 //  Description: Returns the GraphicsPipe that this DisplayRegion is
00146 //               ultimately associated with, or NULL if no pipe is
00147 //               associated.
00148 ////////////////////////////////////////////////////////////////////
00149 GraphicsPipe *DisplayRegion::
00150 get_pipe() const {
00151   return (_window != (GraphicsOutput *)NULL) ? _window->get_pipe() : NULL;
00152 }
00153 
00154 ////////////////////////////////////////////////////////////////////
00155 //     Function: DisplayRegion::is_stereo
00156 //       Access: Published, Virtual
00157 //  Description: Returns true if this is a StereoDisplayRegion, false
00158 //               otherwise.
00159 ////////////////////////////////////////////////////////////////////
00160 bool DisplayRegion::
00161 is_stereo() const {
00162   return false;
00163 }
00164 
00165 ////////////////////////////////////////////////////////////////////
00166 //     Function: DisplayRegion::set_camera
00167 //       Access: Published, Virtual
00168 //  Description: Sets the camera that is associated with this
00169 //               DisplayRegion.  There is a one-to-many association
00170 //               between cameras and DisplayRegions; one camera may be
00171 //               shared by multiple DisplayRegions.
00172 //
00173 //               The camera is actually set via a NodePath, which
00174 //               clarifies which instance of the camera (if there
00175 //               happen to be multiple instances) we should use.
00176 ////////////////////////////////////////////////////////////////////
00177 void DisplayRegion::
00178 set_camera(const NodePath &camera) {
00179   int pipeline_stage = Thread::get_current_pipeline_stage();
00180   nassertv(pipeline_stage == 0);
00181   CDWriter cdata(_cycler);
00182 
00183   Camera *camera_node = (Camera *)NULL;
00184   if (!camera.is_empty()) {
00185     DCAST_INTO_V(camera_node, camera.node());
00186   }
00187 
00188   if (camera_node != cdata->_camera_node) {
00189     // Note that these operations on the DisplayRegion are not
00190     // pipelined: they operate across all pipeline stages.  Since we
00191     // have already asserted we are running in pipeline stage 0, no
00192     // problem.
00193     if (cdata->_camera_node != (Camera *)NULL) {
00194       // We need to tell the old camera we're not using him anymore.
00195       cdata->_camera_node->remove_display_region(this);
00196     }
00197     cdata->_camera_node = camera_node;
00198     if (cdata->_camera_node != (Camera *)NULL) {
00199       // Now tell the new camera we are using him.
00200       cdata->_camera_node->add_display_region(this);
00201     }
00202   }
00203 
00204   cdata->_camera = camera;
00205 }
00206 
00207 ////////////////////////////////////////////////////////////////////
00208 //     Function: DisplayRegion::set_active
00209 //       Access: Published, Virtual
00210 //  Description: Sets the active flag associated with the
00211 //               DisplayRegion.  If the DisplayRegion is marked
00212 //               inactive, nothing is rendered.
00213 ////////////////////////////////////////////////////////////////////
00214 void DisplayRegion::
00215 set_active(bool active) {
00216   int pipeline_stage = Thread::get_current_pipeline_stage();
00217   nassertv(pipeline_stage == 0);
00218   CDLockedReader cdata(_cycler);
00219 
00220   if (active != cdata->_active) {
00221     CDWriter cdataw(_cycler, cdata);
00222     cdataw->_active = active;
00223     win_display_regions_changed();
00224   }
00225 }
00226 
00227 ////////////////////////////////////////////////////////////////////
00228 //     Function: DisplayRegion::set_sort
00229 //       Access: Published, Virtual
00230 //  Description: Sets the sort value associated with the
00231 //               DisplayRegion.  Within a window, DisplayRegions will
00232 //               be rendered in order from the lowest sort value to
00233 //               the highest.
00234 ////////////////////////////////////////////////////////////////////
00235 void DisplayRegion::
00236 set_sort(int sort) {
00237   nassertv(Thread::get_current_pipeline_stage() == 0);
00238   CDLockedReader cdata(_cycler);
00239 
00240   if (sort != cdata->_sort) {
00241     CDWriter cdataw(_cycler, cdata);
00242     cdataw->_sort = sort;
00243     win_display_regions_changed();
00244   }
00245 }
00246 
00247 ////////////////////////////////////////////////////////////////////
00248 //     Function: DisplayRegion::set_stereo_channel
00249 //       Access: Published, Virtual
00250 //  Description: Specifies whether the DisplayRegion represents the
00251 //               left or right channel of a stereo pair, or whether it
00252 //               is a normal, monocular image.  This automatically
00253 //               adjusts the lens that is used to render to this
00254 //               DisplayRegion to its left or right eye, according to
00255 //               the lens's stereo properties.
00256 //
00257 //               When the DisplayRegion is attached to a stereo window
00258 //               (one for which is_stereo() returns true), this also
00259 //               specifies which physical channel the DisplayRegion
00260 //               renders to.
00261 //
00262 //               Normally you would create at least two DisplayRegions
00263 //               for a stereo window, one for each of the left and
00264 //               right channels.  The two DisplayRegions may share the
00265 //               same camera (and thus the same lens); this parameter
00266 //               is used to control the exact properties of the lens
00267 //               when it is used to render into this DisplayRegion.
00268 //
00269 //               Also see the StereoDisplayRegion, which automates
00270 //               managing a pair of left/right DisplayRegions.
00271 //
00272 //               An ordinary DisplayRegion may be set to SC_mono,
00273 //               SC_left, or SC_right.  You may set SC_stereo only on
00274 //               a StereoDisplayRegion.
00275 ////////////////////////////////////////////////////////////////////
00276 void DisplayRegion::
00277 set_stereo_channel(Lens::StereoChannel stereo_channel) {
00278   nassertv(is_stereo() || stereo_channel != Lens::SC_stereo);
00279 
00280   nassertv(Thread::get_current_pipeline_stage() == 0);
00281 
00282   CDWriter cdata(_cycler);
00283   cdata->_stereo_channel = stereo_channel;
00284 }
00285 
00286 ////////////////////////////////////////////////////////////////////
00287 //     Function: DisplayRegion::set_incomplete_render
00288 //       Access: Published, Virtual
00289 //  Description: Sets the incomplete_render flag.  When this is
00290 //               true, the frame will be rendered even if some of the
00291 //               geometry or textures in the scene are not available
00292 //               (e.g. they have been temporarily paged out).  When
00293 //               this is false, the frame will be held up while this
00294 //               data is reloaded.
00295 //
00296 //               This flag may also be set on the
00297 //               GraphicsStateGuardian.  It will be considered true
00298 //               for a given DisplayRegion only if it is true on both
00299 //               the GSG and on the DisplayRegion.
00300 //
00301 //               See GraphicsStateGuardian::set_incomplete_render()
00302 //               for more detail.
00303 ////////////////////////////////////////////////////////////////////
00304 void DisplayRegion::
00305 set_incomplete_render(bool incomplete_render) {
00306   _incomplete_render = incomplete_render;
00307 }
00308 
00309 ////////////////////////////////////////////////////////////////////
00310 //     Function: DisplayRegion::set_texture_reload_priority
00311 //       Access: Published, Virtual
00312 //  Description: Specifies an integer priority which is assigned to
00313 //               any asynchronous texture reload requests spawned
00314 //               while processing this DisplayRegion.  This controls
00315 //               which textures are loaded first when multiple
00316 //               textures need to be reloaded at once; it also
00317 //               controls the relative priority between asynchronous
00318 //               texture loads and asynchronous model or animation
00319 //               loads.
00320 //
00321 //               Specifying a larger number here makes the textures
00322 //               rendered by this DisplayRegion load up first.  This
00323 //               may be particularly useful to do, for instance, for
00324 //               the DisplayRegion that renders the gui.
00325 ////////////////////////////////////////////////////////////////////
00326 void DisplayRegion::
00327 set_texture_reload_priority(int texture_reload_priority) {
00328   _texture_reload_priority = texture_reload_priority;
00329 }
00330 
00331 ////////////////////////////////////////////////////////////////////
00332 //     Function: DisplayRegion::set_cull_traverser
00333 //       Access: Published, Virtual
00334 //  Description: Specifies the CullTraverser that will be used to draw
00335 //               the contents of this DisplayRegion.  Normally the
00336 //               default CullTraverser is sufficient, but this may be
00337 //               changed to change the default cull behavior.
00338 ////////////////////////////////////////////////////////////////////
00339 void DisplayRegion::
00340 set_cull_traverser(CullTraverser *trav) {
00341   _trav = trav;
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: DisplayRegion::get_cull_traverser
00346 //       Access: Published
00347 //  Description: Returns the CullTraverser that will be used to draw
00348 //               the contents of this DisplayRegion.
00349 ////////////////////////////////////////////////////////////////////
00350 CullTraverser *DisplayRegion::
00351 get_cull_traverser() {
00352   if (_trav == (CullTraverser *)NULL) {
00353     _trav = new CullTraverser;
00354   }
00355   return _trav;
00356 }
00357 
00358 ////////////////////////////////////////////////////////////////////
00359 //     Function: DisplayRegion::set_cube_map_index
00360 //       Access: Published, Virtual
00361 //  Description: This is a special parameter that is only used when
00362 //               rendering the faces of a cube map.  Normally you
00363 //               should not need to set it directly.  This sets up the
00364 //               DisplayRegion to render to the nth cube map face; the
00365 //               value must be between 0 and 5, inclusive.  A normal
00366 //               DisplayRegion that is not associated with any
00367 //               particular cube map should be set to -1.
00368 ////////////////////////////////////////////////////////////////////
00369 void DisplayRegion::
00370 set_cube_map_index(int cube_map_index) {
00371   int pipeline_stage = Thread::get_current_pipeline_stage();
00372   nassertv(pipeline_stage == 0);
00373   CDWriter cdata(_cycler);
00374   cdata->_cube_map_index = cube_map_index;
00375 }
00376 
00377 ////////////////////////////////////////////////////////////////////
00378 //     Function: DisplayRegion::output
00379 //       Access: Published, Virtual
00380 //  Description:
00381 ////////////////////////////////////////////////////////////////////
00382 void DisplayRegion::
00383 output(ostream &out) const {
00384   CDReader cdata(_cycler);
00385   out << "DisplayRegion(" << cdata->_l << " " << cdata->_r << " "
00386       << cdata->_b << " " << cdata->_t << ")=pixels(" << cdata->_pl
00387       << " " << cdata->_pr << " " << cdata->_pb << " " << cdata->_pt
00388       << ")";
00389 }
00390 
00391 ////////////////////////////////////////////////////////////////////
00392 //     Function: DisplayRegion::make_screenshot_filename
00393 //       Access: Published, Static
00394 //  Description: Synthesizes a suitable default filename for passing
00395 //               to save_screenshot().
00396 //
00397 //               The default filename is generated from the supplied
00398 //               prefix and from the Config variable
00399 //               screenshot-filename, which contains the following
00400 //               strings:
00401 //
00402 //                 %~p - the supplied prefix
00403 //                 %~f - the frame count
00404 //                 %~e - the value of screenshot-extension
00405 //                 All other % strings in strftime().
00406 ////////////////////////////////////////////////////////////////////
00407 Filename DisplayRegion::
00408 make_screenshot_filename(const string &prefix) {
00409   time_t now = time(NULL);
00410   struct tm *ttm = localtime(&now);
00411   int frame_count = ClockObject::get_global_clock()->get_frame_count();
00412 
00413   static const int buffer_size = 1024;
00414   char buffer[buffer_size];
00415 
00416   ostringstream filename_strm;
00417 
00418   size_t i = 0;
00419   while (i < screenshot_filename.length()) {
00420     char ch1 = screenshot_filename[i++];
00421     if (ch1 == '%' && i < screenshot_filename.length()) {
00422       char ch2 = screenshot_filename[i++];
00423       if (ch2 == '~' && i < screenshot_filename.length()) {
00424         char ch3 = screenshot_filename[i++];
00425         switch (ch3) {
00426         case 'p':
00427           filename_strm << prefix;
00428           break;
00429 
00430         case 'f':
00431           filename_strm << frame_count;
00432           break;
00433 
00434         case 'e':
00435           filename_strm << screenshot_extension;
00436           break;
00437         }
00438 
00439       } else {
00440         // Use strftime() to decode the percent code.
00441         char format[3] = {'%', ch2, '\0'};
00442         if (strftime(buffer, buffer_size, format, ttm)) {
00443           for (char *b = buffer; *b != '\0'; b++) {
00444             switch (*b) {
00445             case ' ':
00446             case ':':
00447             case '/':
00448               filename_strm << '-';
00449               break;
00450 
00451             case '\n':
00452               break;
00453 
00454             default:
00455               filename_strm << *b;
00456             }
00457           }
00458         }
00459       }
00460     } else {
00461       filename_strm << ch1;
00462     }
00463   }
00464 
00465   return Filename(filename_strm.str());
00466 }
00467 
00468 
00469 ////////////////////////////////////////////////////////////////////
00470 //     Function: DisplayRegion::save_screenshot_default
00471 //       Access: Published
00472 //  Description: Saves a screenshot of the region to a default
00473 //               filename, and returns the filename, or empty string
00474 //               if the screenshot failed.  The filename is generated
00475 //               by make_screenshot_filename().
00476 ////////////////////////////////////////////////////////////////////
00477 Filename DisplayRegion::
00478 save_screenshot_default(const string &prefix) {
00479   Filename filename = make_screenshot_filename(prefix);
00480   if (save_screenshot(filename)) {
00481     return filename;
00482   }
00483   return Filename();
00484 }
00485 
00486 ////////////////////////////////////////////////////////////////////
00487 //     Function: DisplayRegion::save_screenshot
00488 //       Access: Published
00489 //  Description: Saves a screenshot of the region to the indicated
00490 //               filename.  Returns true on success, false on failure.
00491 ////////////////////////////////////////////////////////////////////
00492 bool DisplayRegion::
00493 save_screenshot(const Filename &filename, const string &image_comment) {
00494   PNMImage image;
00495   if (!get_screenshot(image)) {
00496     return false;
00497   }
00498 
00499   image.set_comment(image_comment);
00500   if (!image.write(filename)) {
00501     return false;
00502   }
00503   return true;
00504 }
00505 
00506 ////////////////////////////////////////////////////////////////////
00507 //     Function: DisplayRegion::get_screenshot
00508 //       Access: Published
00509 //  Description: Captures the most-recently rendered image from the
00510 //               framebuffer into the indicated PNMImage.  Returns
00511 //               true on success, false on failure.
00512 ////////////////////////////////////////////////////////////////////
00513 bool DisplayRegion::
00514 get_screenshot(PNMImage &image) {
00515   Thread *current_thread = Thread::get_current_thread();
00516 
00517   GraphicsOutput *window = get_window();
00518   nassertr(window != (GraphicsOutput *)NULL, false);
00519   
00520   GraphicsStateGuardian *gsg = window->get_gsg();
00521   nassertr(gsg != (GraphicsStateGuardian *)NULL, false);
00522   
00523   if (!window->begin_frame(GraphicsOutput::FM_refresh, current_thread)) {
00524     return false;
00525   }
00526 
00527   // Create a temporary texture to receive the framebuffer image.
00528   PT(Texture) tex = new Texture;
00529   
00530   RenderBuffer buffer = gsg->get_render_buffer(get_screenshot_buffer_type(),
00531                                                _window->get_fb_properties());
00532   if (!gsg->framebuffer_copy_to_ram(tex, -1, this, buffer)) {
00533     return false;
00534   }
00535   
00536   window->end_frame(GraphicsOutput::FM_refresh, current_thread);
00537   
00538   if (!tex->store(image)) {
00539     return false;
00540   }
00541   
00542   return true;
00543 }
00544 
00545 ////////////////////////////////////////////////////////////////////
00546 //     Function: DisplayRegion::make_cull_result_graph
00547 //       Access: Published
00548 //  Description: Returns a special scene graph constructed to
00549 //               represent the results of the last frame's cull
00550 //               operation.
00551 //
00552 //               This will be a hierarchy of nodes, one node for each
00553 //               bin, each of which will in term be a parent of a
00554 //               number of GeomNodes, representing the geometry drawn
00555 //               in each bin.
00556 //
00557 //               This is useful mainly for high-level debugging and
00558 //               abstraction tools; it should not be mistaken for the
00559 //               low-level cull result itself, which is constructed
00560 //               and maintained internally.  No such scene graph is
00561 //               normally constructed during the rendering of a frame;
00562 //               this is an artificial construct created for the
00563 //               purpose of making it easy to analyze the results of
00564 //               the cull operation.
00565 ////////////////////////////////////////////////////////////////////
00566 PT(PandaNode) DisplayRegion::
00567 make_cull_result_graph() {
00568   CullResult *cull_result = get_cull_result(Thread::get_current_thread());
00569   if (cull_result == (CullResult *)NULL) {
00570     return NULL;
00571   }
00572   return cull_result->make_result_graph();
00573 }
00574 
00575 ////////////////////////////////////////////////////////////////////
00576 //     Function: DisplayRegion::compute_pixels
00577 //       Access: Public
00578 //  Description: Computes the pixel locations of the DisplayRegion
00579 //               within its window.  The DisplayRegion will request
00580 //               the size from the window.
00581 ////////////////////////////////////////////////////////////////////
00582 void DisplayRegion::
00583 compute_pixels() {
00584   int pipeline_stage = Thread::get_current_pipeline_stage();
00585   nassertv(pipeline_stage == 0);
00586 
00587   if (_window != (GraphicsOutput *)NULL) {
00588     CDWriter cdata(_cycler);
00589     do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), 
00590                       cdata);
00591   }
00592 }
00593 
00594 ////////////////////////////////////////////////////////////////////
00595 //     Function: DisplayRegion::compute_pixels_all_stages
00596 //       Access: Public
00597 //  Description: Computes the pixel locations of the DisplayRegion
00598 //               within its window.  The DisplayRegion will request
00599 //               the size from the window.
00600 ////////////////////////////////////////////////////////////////////
00601 void DisplayRegion::
00602 compute_pixels_all_stages() {
00603   int pipeline_stage = Thread::get_current_pipeline_stage();
00604   nassertv(pipeline_stage == 0);
00605 
00606   if (_window != (GraphicsOutput *)NULL) {
00607     OPEN_ITERATE_ALL_STAGES(_cycler) {
00608       CDStageWriter cdata(_cycler, pipeline_stage);
00609       do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), 
00610                         cdata);
00611     }
00612     CLOSE_ITERATE_ALL_STAGES(_cycler);
00613   }
00614 }
00615 
00616 ////////////////////////////////////////////////////////////////////
00617 //     Function: DisplayRegion::compute_pixels
00618 //       Access: Public
00619 //  Description: Computes the pixel locations of the DisplayRegion
00620 //               within its window, given the size of the window in
00621 //               pixels.
00622 ////////////////////////////////////////////////////////////////////
00623 void DisplayRegion::
00624 compute_pixels(int x_size, int y_size) {
00625   int pipeline_stage = Thread::get_current_pipeline_stage();
00626   nassertv(pipeline_stage == 0);
00627   CDWriter cdata(_cycler);
00628   do_compute_pixels(x_size, y_size, cdata);
00629 }
00630 
00631 ////////////////////////////////////////////////////////////////////
00632 //     Function: DisplayRegion::compute_pixels_all_stages
00633 //       Access: Public
00634 //  Description: Performs a compute_pixels() operation for all stages
00635 //               of the pipeline.  This is appropriate, for instance,
00636 //               when a window changes sizes, since this is a global
00637 //               operation; and you want the new window size to be
00638 //               immediately available even to the downstream stages.
00639 ////////////////////////////////////////////////////////////////////
00640 void DisplayRegion::
00641 compute_pixels_all_stages(int x_size, int y_size) {
00642   OPEN_ITERATE_ALL_STAGES(_cycler) {
00643     CDStageWriter cdata(_cycler, pipeline_stage);
00644     do_compute_pixels(x_size, y_size, cdata);
00645   } 
00646   CLOSE_ITERATE_ALL_STAGES(_cycler);
00647 }
00648 
00649 ////////////////////////////////////////////////////////////////////
00650 //     Function: DisplayRegion::supports_pixel_zoom
00651 //       Access: Public, Virtual
00652 //  Description: Returns true if a call to set_pixel_zoom() will be
00653 //               respected, false if it will be ignored.  If this
00654 //               returns false, then get_pixel_factor() will always
00655 //               return 1.0, regardless of what value you specify for
00656 //               set_pixel_zoom().
00657 //
00658 //               This may return false if the underlying renderer
00659 //               doesn't support pixel zooming, or if you have called
00660 //               this on a DisplayRegion that doesn't have both
00661 //               set_clear_color() and set_clear_depth() enabled.
00662 ////////////////////////////////////////////////////////////////////
00663 bool DisplayRegion::
00664 supports_pixel_zoom() const {
00665   if (_window != (GraphicsOutput *)NULL) {
00666     if (_window->supports_pixel_zoom()) {
00667       return get_clear_color_active() && get_clear_depth_active();
00668     }
00669   }
00670   return false;
00671 }
00672 
00673 ////////////////////////////////////////////////////////////////////
00674 //     Function: DisplayRegion::win_display_regions_changed
00675 //       Access: Private
00676 //  Description: Intended to be called when the active state on a
00677 //               nested channel or layer or display region changes,
00678 //               forcing the window to recompute its list of active
00679 //               display regions.  It is assumed the lock is already
00680 //               held.
00681 ////////////////////////////////////////////////////////////////////
00682 void DisplayRegion::
00683 win_display_regions_changed() {
00684   if (_window != (GraphicsOutput *)NULL) {
00685     _window->win_display_regions_changed();
00686   }
00687 }
00688 
00689 ////////////////////////////////////////////////////////////////////
00690 //     Function: DisplayRegion::do_compute_pixels
00691 //       Access: Private
00692 //  Description: The private implementation of compute_pixels, this
00693 //               assumes that we already have the lock.
00694 ////////////////////////////////////////////////////////////////////
00695 void DisplayRegion::
00696 do_compute_pixels(int x_size, int y_size, CData *cdata) {
00697   if (display_cat.is_debug()) {
00698     display_cat.debug()
00699       << "DisplayRegion::do_compute_pixels(" << x_size << ", " << y_size << ")\n";
00700   }
00701 
00702   cdata->_pl = int((cdata->_l * x_size) + 0.5);
00703   cdata->_pr = int((cdata->_r * x_size) + 0.5);
00704 
00705   nassertv(_window != (GraphicsOutput *)NULL);
00706   if (_window->get_inverted()) {
00707     // The window is inverted; compute the DisplayRegion accordingly.
00708     cdata->_pb = int(((1.0f - cdata->_t) * y_size) + 0.5);
00709     cdata->_pt = int(((1.0f - cdata->_b) * y_size) + 0.5);
00710     cdata->_pbi = int((cdata->_t * y_size) + 0.5);
00711     cdata->_pti = int((cdata->_b * y_size) + 0.5);
00712 
00713   } else {
00714     // The window is normal.
00715     cdata->_pb = int((cdata->_b * y_size) + 0.5);
00716     cdata->_pt = int((cdata->_t * y_size) + 0.5);
00717     cdata->_pbi = int(((1.0f - cdata->_b) * y_size) + 0.5);
00718     cdata->_pti = int(((1.0f - cdata->_t) * y_size) + 0.5);
00719   }
00720 }
00721 
00722 ////////////////////////////////////////////////////////////////////
00723 //     Function: DisplayRegion::set_active_index
00724 //       Access: Private
00725 //  Description: This is called by GraphicsOutput to indicate that the
00726 //               index of this DisplayRegion within the window's list
00727 //               of active DisplayRegions might have changed.  The
00728 //               index number will be -1 if the DisplayRegion is not
00729 //               active.
00730 //
00731 //               This is primarily intended only for updating the
00732 //               PStatCollector name appropriately.
00733 ////////////////////////////////////////////////////////////////////
00734 void DisplayRegion::
00735 set_active_index(int index) {
00736 #ifdef DO_PSTATS
00737   ostringstream strm;
00738   strm << "dr_" << index;
00739   string name = strm.str();
00740 
00741   _cull_region_pcollector = PStatCollector(_window->get_cull_window_pcollector(), name);
00742   _draw_region_pcollector = PStatCollector(_window->get_draw_window_pcollector(), name);
00743 #endif  // DO_PSTATS
00744 }
00745 
00746 ////////////////////////////////////////////////////////////////////
00747 //     Function: DisplayRegion::CData::Constructor
00748 //       Access: Public
00749 //  Description:
00750 ////////////////////////////////////////////////////////////////////
00751 DisplayRegion::CData::
00752 CData() :
00753   _l(0.), _r(1.), _b(0.), _t(1.),
00754   _pl(0), _pr(0), _pb(0), _pt(0),
00755   _pbi(0), _pti(0), _lens_index(0),
00756   _camera_node((Camera *)NULL),
00757   _active(true),
00758   _sort(0),
00759   _stereo_channel(Lens::SC_mono),
00760   _cube_map_index(-1)
00761 {
00762 }
00763 
00764 ////////////////////////////////////////////////////////////////////
00765 //     Function: DisplayRegion::CData::Copy Constructor
00766 //       Access: Public
00767 //  Description:
00768 ////////////////////////////////////////////////////////////////////
00769 DisplayRegion::CData::
00770 CData(const DisplayRegion::CData &copy) :
00771   _l(copy._l),
00772   _r(copy._r),
00773   _b(copy._b),
00774   _t(copy._t),
00775   _pl(copy._pl),
00776   _pr(copy._pr),
00777   _pb(copy._pb),
00778   _pt(copy._pt),
00779   _pbi(copy._pbi),
00780   _pti(copy._pti),
00781   _lens_index(copy._lens_index),
00782   _camera(copy._camera),
00783   _camera_node(copy._camera_node),
00784   _active(copy._active),
00785   _sort(copy._sort),
00786   _stereo_channel(copy._stereo_channel),
00787   _cube_map_index(copy._cube_map_index)
00788 {
00789 }
00790 
00791 ////////////////////////////////////////////////////////////////////
00792 //     Function: DisplayRegion::CData::make_copy
00793 //       Access: Public, Virtual
00794 //  Description:
00795 ////////////////////////////////////////////////////////////////////
00796 CycleData *DisplayRegion::CData::
00797 make_copy() const {
00798   return new CData(*this);
00799 }
00800 
00801 ////////////////////////////////////////////////////////////////////
00802 //     Function: DisplayRegion::CDataCull::make_copy
00803 //       Access: Public, Virtual
00804 //  Description:
00805 ////////////////////////////////////////////////////////////////////
00806 CycleData *DisplayRegion::CDataCull::
00807 make_copy() const {
00808   return new CDataCull(*this);
00809 }
00810 
00811 ////////////////////////////////////////////////////////////////////
00812 //     Function: DisplayRegionPipelineReader::get_pipe
00813 //       Access: Public
00814 //  Description: Returns the GraphicsPipe that this DisplayRegion is
00815 //               ultimately associated with, or NULL if no pipe is
00816 //               associated.
00817 ////////////////////////////////////////////////////////////////////
00818 GraphicsPipe *DisplayRegionPipelineReader::
00819 get_pipe() const {
00820   return (_object->_window != (GraphicsOutput *)NULL) ? _object->_window->get_pipe() : NULL;
00821 }
 All Classes Functions Variables Enumerations