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