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