Panda3D
|
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 ©) : 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 ©) : 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 }