15 #include "graphicsEngine.h" 16 #include "graphicsPipe.h" 17 #include "parasiteBuffer.h" 18 #include "config_gobj.h" 19 #include "config_display.h" 21 #include "drawCullHandler.h" 22 #include "binCullHandler.h" 23 #include "cullResult.h" 24 #include "cullTraverser.h" 25 #include "clockObject.h" 26 #include "pStatTimer.h" 27 #include "pStatGPUTimer.h" 28 #include "pStatClient.h" 29 #include "pStatCollector.h" 30 #include "mutexHolder.h" 31 #include "reMutexHolder.h" 32 #include "lightReMutexHolder.h" 33 #include "cullFaceAttrib.h" 34 #include "string_utils.h" 35 #include "geomCacheManager.h" 36 #include "renderState.h" 37 #include "transformState.h" 40 #include "throw_event.h" 42 #include "cullableObject.h" 43 #include "geomVertexArrayData.h" 44 #include "omniBoundingVolume.h" 45 #include "vertexDataSaveFile.h" 46 #include "vertexDataBook.h" 47 #include "vertexDataPage.h" 48 #include "config_pgraph.h" 49 #include "displayRegionCullCallbackData.h" 50 #include "displayRegionDrawCallbackData.h" 51 #include "callbackGraphicsWindow.h" 54 #define WINDOWS_LEAN_AND_MEAN 57 #undef WINDOWS_LEAN_AND_MEAN 64 PStatCollector GraphicsEngine::_wait_pcollector(
"Wait:Thread sync");
66 PStatCollector GraphicsEngine::_app_pcollector(
"App:Show code:General");
67 PStatCollector GraphicsEngine::_render_frame_pcollector(
"App:render_frame");
71 PStatCollector GraphicsEngine::_cull_setup_pcollector(
"Cull:Setup");
76 PStatCollector GraphicsEngine::_flip_begin_pcollector(
"Wait:Flip:Begin");
77 PStatCollector GraphicsEngine::_flip_end_pcollector(
"Wait:Flip:End");
78 PStatCollector GraphicsEngine::_transform_states_pcollector(
"TransformStates");
79 PStatCollector GraphicsEngine::_transform_states_unused_pcollector(
"TransformStates:Unused");
80 PStatCollector GraphicsEngine::_render_states_pcollector(
"RenderStates");
81 PStatCollector GraphicsEngine::_render_states_unused_pcollector(
"RenderStates:Unused");
82 PStatCollector GraphicsEngine::_cyclers_pcollector(
"PipelineCyclers");
83 PStatCollector GraphicsEngine::_dirty_cyclers_pcollector(
"Dirty PipelineCyclers");
87 PStatCollector GraphicsEngine::_sw_sprites_pcollector(
"SW Sprites");
88 PStatCollector GraphicsEngine::_vertex_data_small_pcollector(
"Vertex Data:Small");
89 PStatCollector GraphicsEngine::_vertex_data_independent_pcollector(
"Vertex Data:Independent");
90 PStatCollector GraphicsEngine::_vertex_data_pending_pcollector(
"Vertex Data:Pending");
91 PStatCollector GraphicsEngine::_vertex_data_resident_pcollector(
"Vertex Data:Resident");
92 PStatCollector GraphicsEngine::_vertex_data_compressed_pcollector(
"Vertex Data:Compressed");
93 PStatCollector GraphicsEngine::_vertex_data_unused_disk_pcollector(
"Vertex Data:Disk:Unused");
94 PStatCollector GraphicsEngine::_vertex_data_used_disk_pcollector(
"Vertex Data:Disk:Used");
98 PStatCollector GraphicsEngine::_cnode_volume_pcollector(
"Collision Volumes:CollisionNode");
99 PStatCollector GraphicsEngine::_gnode_volume_pcollector(
"Collision Volumes:GeomNode");
100 PStatCollector GraphicsEngine::_geom_volume_pcollector(
"Collision Volumes:Geom");
101 PStatCollector GraphicsEngine::_node_volume_pcollector(
"Collision Volumes:PandaNode");
102 PStatCollector GraphicsEngine::_volume_pcollector(
"Collision Volumes:CollisionSolid");
103 PStatCollector GraphicsEngine::_test_pcollector(
"Collision Tests:CollisionSolid");
104 PStatCollector GraphicsEngine::_volume_polygon_pcollector(
"Collision Volumes:CollisionPolygon");
105 PStatCollector GraphicsEngine::_test_polygon_pcollector(
"Collision Tests:CollisionPolygon");
106 PStatCollector GraphicsEngine::_volume_plane_pcollector(
"Collision Volumes:CollisionPlane");
107 PStatCollector GraphicsEngine::_test_plane_pcollector(
"Collision Tests:CollisionPlane");
108 PStatCollector GraphicsEngine::_volume_sphere_pcollector(
"Collision Volumes:CollisionSphere");
109 PStatCollector GraphicsEngine::_test_sphere_pcollector(
"Collision Tests:CollisionSphere");
110 PStatCollector GraphicsEngine::_volume_box_pcollector(
"Collision Volumes:CollisionBox");
111 PStatCollector GraphicsEngine::_test_box_pcollector(
"Collision Tests:CollisionBox");
112 PStatCollector GraphicsEngine::_volume_tube_pcollector(
"Collision Volumes:CollisionTube");
113 PStatCollector GraphicsEngine::_test_tube_pcollector(
"Collision Tests:CollisionTube");
114 PStatCollector GraphicsEngine::_volume_inv_sphere_pcollector(
"Collision Volumes:CollisionInvSphere");
115 PStatCollector GraphicsEngine::_test_inv_sphere_pcollector(
"Collision Tests:CollisionInvSphere");
116 PStatCollector GraphicsEngine::_volume_geom_pcollector(
"Collision Volumes:CollisionGeom");
117 PStatCollector GraphicsEngine::_test_geom_pcollector(
"Collision Tests:CollisionGeom");
118 PStatCollector GraphicsEngine::_occlusion_untested_pcollector(
"Occlusion results:Not tested");
119 PStatCollector GraphicsEngine::_occlusion_passed_pcollector(
"Occlusion results:Visible");
120 PStatCollector GraphicsEngine::_occlusion_failed_pcollector(
"Occlusion results:Occluded");
121 PStatCollector GraphicsEngine::_occlusion_tests_pcollector(
"Occlusion tests");
130 INLINE
static bool operator < (
const CullKey &a,
const CullKey &b) {
131 if (a._gsg != b._gsg) {
132 return a._gsg < b._gsg;
134 if (a._camera != b._camera) {
135 return a._camera < b._camera;
137 return a._lens_index < b._lens_index;
152 _lock(
"GraphicsEngine::_lock"),
153 _loaded_textures_lock(
"GraphicsEngine::_loaded_textures_lock")
155 if (_pipeline == (
Pipeline *)NULL) {
159 _windows_sorted =
true;
160 _window_sort_index = 0;
161 _needs_open_windows =
false;
166 <<
"Using threading model " << _threading_model <<
"\n";
168 _auto_flip = auto_flip;
169 _portal_enabled =
false;
170 _flip_state = FS_flip;
172 _singular_warning_last_frame =
false;
173 _singular_warning_this_frame =
false;
185 if (_app_pcollector.is_started()) {
186 _app_pcollector.stop();
204 display_cat.warning()
205 <<
"Threading model " << threading_model
206 <<
" requested but threading is not available. Ignoring.\n";
211 #ifndef THREADED_PIPELINE 213 display_cat.warning()
214 <<
"Threading model " << threading_model
215 <<
" requested but multithreaded render pipelines not enabled in build.\n";
216 if (!allow_nonpipeline_threads) {
217 display_cat.warning()
218 <<
"Ignoring requested threading model.\n";
221 display_cat.warning()
222 <<
"Danger! Creating requested render threads anyway!\n";
224 #endif // THREADED_PIPELINE 226 _threading_model = threading_model;
240 result = _threading_model;
266 const string &name,
int sort,
306 int x_size = 0, y_size = 0;
311 if ((x_size == 0)&&(y_size == 0)) {
312 flags |= GraphicsPipe::BF_size_track_host;
354 nassertr(pipe == gsg->
get_pipe(), NULL);
361 if ((flags & GraphicsPipe::BF_require_callback_window)!=0) {
366 this_gsg = pipe->make_callback_gsg(
this);
370 window->_sort = sort;
371 do_add_window(window, threading_model);
372 do_add_gsg(window->
get_gsg(), pipe, threading_model);
373 display_cat.info() <<
"Created output of type CallbackGraphicsWindow\n";
384 bool can_use_parasite =
false;
386 ((flags&GraphicsPipe::BF_require_window)==0)&&
387 ((flags&GraphicsPipe::BF_require_callback_window)==0)&&
388 ((flags&GraphicsPipe::BF_refuse_parasite)==0)&&
389 ((flags&GraphicsPipe::BF_can_bind_color)==0)&&
390 ((flags&GraphicsPipe::BF_can_bind_every)==0)&&
391 ((flags&GraphicsPipe::BF_rtt_cumulative)==0)&&
392 ((flags&GraphicsPipe::BF_can_bind_layered)==0)) {
393 if ((flags&GraphicsPipe::BF_fb_props_optional) ||
395 can_use_parasite =
true;
404 if ((prefer_parasite_buffer) &&
405 (can_use_parasite) &&
406 (x_size <= host->get_x_size())&&
407 (y_size <= host->get_y_size())&&
410 buffer->_sort = sort;
411 do_add_window(buffer, threading_model);
412 do_add_gsg(host->
get_gsg(), pipe, threading_model);
413 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
420 if (force_parasite_buffer && can_use_parasite) {
422 buffer->_sort = sort;
423 do_add_window(buffer, threading_model);
424 do_add_gsg(host->
get_gsg(), pipe, threading_model);
425 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
431 for (
int retry=0; retry<10; retry++) {
432 bool precertify =
false;
434 pipe->make_output(name, fb_prop, win_prop, flags,
this, gsg, host, retry, precertify);
436 window->_sort = sort;
437 if ((precertify) && (gsg != 0) && (window->
get_gsg()==gsg)) {
438 do_add_window(window, threading_model);
439 do_add_gsg(window->
get_gsg(), pipe, threading_model);
441 <<
"Created output of type " << window->get_type() <<
"\n";
444 do_add_window(window, threading_model);
447 do_add_gsg(window->
get_gsg(), pipe, threading_model);
449 <<
"Created output of type " << window->get_type() <<
"\n";
454 if (flags & GraphicsPipe::BF_fb_props_optional) {
455 display_cat.warning()
456 <<
"FrameBufferProperties available less than requested.\n";
457 display_cat.warning(
false)
458 <<
" requested: " << fb_prop <<
"\n" 463 <<
"Could not get requested FrameBufferProperties; abandoning window.\n";
464 display_cat.error(
false)
465 <<
" requested: " << fb_prop <<
"\n" 470 << window->get_type() <<
" wouldn't open; abandoning.\n";
471 display_cat.debug(
false)
472 <<
" requested: " << fb_prop <<
"\n";
477 nassertr(removed, NULL);
485 if (can_use_parasite) {
487 buffer->_sort = sort;
488 do_add_window(buffer, threading_model);
489 do_add_gsg(host->
get_gsg(), pipe, threading_model);
490 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
512 nassertr(window != NULL,
false);
515 nassertr(
this == window->
get_engine(),
false);
517 window->_sort = sort;
518 do_add_window(window, threading_model);
525 <<
"Added output of type " << window->get_type() <<
"\n";
561 nassertr(window != NULL,
false);
569 if (!_windows_sorted) {
572 count = _windows.erase(ptwin);
579 do_remove_window(window, current_thread);
587 bool any_common =
false;
590 Windows::iterator wi;
591 for (wi = _windows.
begin(); wi != _windows.
end() && !any_common; ++wi) {
611 nassertr(count == 1,
true);
632 old_windows.
swap(_windows);
633 Windows::iterator wi;
634 for (wi = old_windows.
begin(); wi != old_windows.
end(); ++wi) {
636 nassertv(win != NULL);
637 do_remove_window(win, current_thread);
644 _app.do_close(
this, current_thread);
645 _app.do_pending(
this, current_thread);
646 terminate_threads(current_thread);
664 PStatClient::get_global_pstats()->disconnect();
681 Windows::iterator wi;
682 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
698 return _windows.
empty();
709 return _windows.
size();
720 nassertr(n >= 0 && n < (
int)_windows.
size(), NULL);
722 if (!_windows_sorted) {
746 _render_frame_pcollector.start();
747 if (_app_pcollector.is_started()) {
748 _app_pcollector.stop();
752 if (_needs_open_windows) {
763 if (display_cat.is_spam()) {
765 <<
"render_frame() - frame " << global_clock->
get_frame_count() <<
"\n";
771 if (!_windows_sorted) {
775 if (sync_flip && _flip_state != FS_flip) {
776 do_flip_frame(current_thread);
782 Windows::iterator wi;
783 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
785 nassertv(win != NULL);
787 do_remove_window(win, current_thread);
798 int num_drs = win->get_num_active_display_regions();
799 for (
int i = 0; i < num_drs; ++i) {
806 if (scene.is_empty()) {
807 scene = camera_np.
get_top(current_thread);
809 if (!scene.is_empty()) {
810 scene.get_bounds(current_thread);
817 _windows.
swap(new_windows);
823 LoadedTextures::iterator lti;
824 for (lti = _loaded_textures.begin(); lti != _loaded_textures.end(); ++lti) {
825 LoadedTexture < = (*lti);
826 if (lt._tex->get_image_modified() == lt._image_modified) {
827 lt._tex->texture_uploaded();
830 _loaded_textures.clear();
835 _app.do_frame(
this, current_thread);
840 PStatTimer timer(_wait_pcollector, current_thread);
841 Threads::const_iterator ti;
842 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
843 RenderThread *thread = (*ti).second;
844 thread->_cv_mutex.acquire();
846 while (thread->_thread_state != TS_wait) {
847 thread->_cv_done.wait();
852 #if defined(THREADED_PIPELINE) && defined(DO_PSTATS) 853 _cyclers_pcollector.set_level(_pipeline->get_num_cyclers());
854 _dirty_cyclers_pcollector.set_level(_pipeline->get_num_dirty_cyclers());
858 _pipeline->iterate_all_cycler_types(pstats_count_cycler_type,
this);
859 _pipeline->iterate_dirty_cycler_types(pstats_count_dirty_cycler_type,
this);
861 #endif // DEBUG_THREADS 863 #endif // THREADED_PIPELINE && DO_PSTATS 868 TransformState::flush_level();
872 #ifdef THREADED_PIPELINE 874 PStatTimer timer(_cycle_pcollector, current_thread);
877 #endif // THREADED_PIPELINE 879 global_clock->
tick(current_thread);
881 throw_event(
"clock_error");
885 PStatClient::main_tick();
888 CullTraverser::_nodes_pcollector.clear_level();
889 CullTraverser::_geom_nodes_pcollector.clear_level();
890 CullTraverser::_geoms_pcollector.clear_level();
891 GeomCacheManager::_geom_cache_active_pcollector.clear_level();
892 GeomCacheManager::_geom_cache_record_pcollector.clear_level();
893 GeomCacheManager::_geom_cache_erase_pcollector.clear_level();
894 GeomCacheManager::_geom_cache_evict_pcollector.clear_level();
896 GraphicsStateGuardian::init_frame_pstats();
898 _transform_states_pcollector.set_level(TransformState::get_num_states());
900 if (pstats_unused_states) {
901 _transform_states_unused_pcollector.set_level(TransformState::get_num_unused_states());
905 _sw_sprites_pcollector.clear_level();
907 _cnode_volume_pcollector.clear_level();
908 _gnode_volume_pcollector.clear_level();
909 _geom_volume_pcollector.clear_level();
910 _node_volume_pcollector.clear_level();
911 _volume_pcollector.clear_level();
912 _test_pcollector.clear_level();
913 _volume_polygon_pcollector.clear_level();
914 _test_polygon_pcollector.clear_level();
915 _volume_plane_pcollector.clear_level();
916 _test_plane_pcollector.clear_level();
917 _volume_sphere_pcollector.clear_level();
918 _test_sphere_pcollector.clear_level();
919 _volume_box_pcollector.clear_level();
920 _test_box_pcollector.clear_level();
921 _volume_tube_pcollector.clear_level();
922 _test_tube_pcollector.clear_level();
923 _volume_inv_sphere_pcollector.clear_level();
924 _test_inv_sphere_pcollector.clear_level();
925 _volume_geom_pcollector.clear_level();
926 _test_geom_pcollector.clear_level();
927 _occlusion_untested_pcollector.clear_level();
928 _occlusion_passed_pcollector.clear_level();
929 _occlusion_failed_pcollector.clear_level();
930 _occlusion_tests_pcollector.clear_level();
943 _vertex_data_small_pcollector.set_level(small_buf);
944 _vertex_data_independent_pcollector.set_level(independent);
945 _vertex_data_pending_pcollector.set_level(pending);
946 _vertex_data_resident_pcollector.set_level(resident);
947 _vertex_data_compressed_pcollector.set_level(compressed);
948 _vertex_data_unused_disk_pcollector.set_level(total_disk - used_disk);
949 _vertex_data_used_disk_pcollector.set_level(used_disk);
957 Threads::const_iterator ti;
958 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
959 RenderThread *thread = (*ti).second;
960 if (thread->_thread_state == TS_wait) {
961 thread->_thread_state = TS_do_frame;
962 thread->_cv_start.notify();
964 thread->_cv_mutex.release();
969 _flip_state = _auto_flip ? FS_flip : FS_draw;
974 if (yield_timeslice) {
977 PStatTimer timer(_yield_pcollector, current_thread);
980 PStatTimer timer(_yield_pcollector, current_thread);
986 _app_pcollector.start();
987 _render_frame_pcollector.stop();
1008 if (!_windows_sorted) {
1009 do_resort_windows();
1014 for (
int i = 0; i < 2; ++i) {
1015 _app.do_windows(
this, current_thread);
1016 _app.do_pending(
this, current_thread);
1018 PStatTimer timer(_wait_pcollector, current_thread);
1019 Threads::const_iterator ti;
1020 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1021 RenderThread *thread = (*ti).second;
1022 thread->_cv_mutex.acquire();
1024 while (thread->_thread_state != TS_wait) {
1025 thread->_cv_done.wait();
1028 thread->_thread_state = TS_do_windows;
1029 thread->_cv_start.notify();
1030 thread->_cv_mutex.release();
1034 _needs_open_windows =
false;
1051 if (_flip_state == FS_draw) {
1052 do_sync_frame(current_thread);
1076 if (_flip_state == FS_draw) {
1077 do_ready_flip(current_thread);
1095 if (_flip_state != FS_flip) {
1096 do_flip_frame(current_thread);
1134 if (draw_name.empty()) {
1141 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1142 RenderThread *thread = (RenderThread *)wr;
1145 while (thread->_thread_state != TS_wait) {
1146 thread->_cv_done.wait();
1181 CPT(
RenderState) state = RenderState::make(sattr);
1184 if (draw_name.empty()) {
1190 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1191 RenderThread *thread = (RenderThread *)wr;
1194 while (thread->_thread_state != TS_wait) {
1195 thread->_cv_done.wait();
1215 if (_global_ptr == NULL) {
1241 _loaded_textures.push_back(LoadedTexture());
1242 LoadedTexture < = _loaded_textures.back();
1263 trav->set_view_frustum(NULL);
1264 if (view_frustum_cull) {
1273 bv->is_of_type(GeometricBoundingVolume::get_class_type()) &&
1274 !bv->is_of_type(OmniBoundingVolume::get_class_type())) {
1280 CPT(TransformState) cull_center_transform =
1282 local_frustum->xform(cull_center_transform->get_mat());
1284 trav->set_view_frustum(local_frustum);
1289 trav->end_traverse();
1299 bool GraphicsEngine::
1300 scene_root_func(
const PandaNode *node) {
1301 return _global_ptr->is_scene_root(node);
1311 bool GraphicsEngine::
1315 Windows::const_iterator wi;
1316 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
1319 int num_display_regions = win->get_num_active_display_regions();
1320 for (
int i = 0; i < num_display_regions; i++) {
1329 DCAST_INTO_R(camera_node, camera.
node(),
false);
1339 scene_root = camera.
get_top(current_thread);
1342 if (scene_root.
node() == node) {
1363 void GraphicsEngine::
1366 window->_sort = sort;
1367 _windows_sorted =
false;
1379 void GraphicsEngine::
1381 Thread *current_thread) {
1382 PStatTimer timer(_cull_pcollector, current_thread);
1384 size_t wlist_size = wlist.
size();
1385 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1390 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1394 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1399 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1400 win->
clear(current_thread);
1402 int num_display_regions = win->get_num_active_display_regions();
1403 for (
int i = 0; i < num_display_regions; i++) {
1406 cull_and_draw_together(win, dr, current_thread);
1409 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1414 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1418 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1434 void GraphicsEngine::
1436 Thread *current_thread) {
1446 if (dr_reader->is_any_clear_active()) {
1450 PT(
SceneSetup) scene_setup = setup_scene(gsg, dr_reader);
1454 }
else if (dr_reader->get_object()->
is_stereo()) {
1457 }
else if (!gsg->
set_scene(scene_setup)) {
1460 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
1478 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1498 void GraphicsEngine::
1500 PStatTimer timer(_cull_pcollector, current_thread);
1502 _singular_warning_last_frame = _singular_warning_this_frame;
1503 _singular_warning_this_frame =
false;
1508 AlreadyCulled already_culled;
1510 size_t wlist_size = wlist.
size();
1511 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1515 int num_display_regions = win->get_num_active_display_regions();
1516 for (
int i = 0; i < num_display_regions; ++i) {
1527 AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(key, (
DisplayRegion *)NULL)).first;
1528 if ((*aci).second == NULL) {
1534 cull_to_bins(win, dr, current_thread);
1546 setup_scene(win->
get_gsg(), dr_reader),
1565 void GraphicsEngine::
1575 PStatTimer timer(_cull_setup_pcollector, current_thread);
1577 scene_setup = setup_scene(gsg, &dr_reader);
1581 cull_result = cull_result->make_next();
1601 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1604 PStatTimer timer(_cull_sort_pcollector, current_thread);
1605 cull_result->
finish_cull(scene_setup, current_thread);
1621 void GraphicsEngine::
1625 size_t wlist_size = wlist.
size();
1626 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1637 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1641 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1646 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1651 win->
clear(current_thread);
1653 if (display_cat.is_spam()) {
1655 <<
"Drawing window " << win->
get_name() <<
"\n";
1657 int num_display_regions = win->get_num_active_display_regions();
1658 for (
int i = 0; i < num_display_regions; ++i) {
1661 draw_bins(win, dr, current_thread);
1665 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1671 win->
get_gsg()->issue_timer_query(GraphicsStateGuardian::_command_latency_pcollector.get_index());
1678 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1689 if (display_cat.is_spam()) {
1691 <<
"Not drawing window " << win->
get_name() <<
"\n";
1696 if (display_cat.is_spam()) {
1698 <<
"Window " << win->
get_name() <<
" is inactive\n";
1711 void GraphicsEngine::
1720 do_draw(cull_result, scene_setup, win, dr, current_thread);
1730 void GraphicsEngine::
1732 Windows::const_iterator wi;
1733 for (wi = wlist.
begin(); wi != wlist.
end(); ++wi) {
1735 if (win->
begin_frame(GraphicsOutput::FM_refresh, current_thread)) {
1736 win->
end_frame(GraphicsOutput::FM_refresh, current_thread);
1748 void GraphicsEngine::
1753 for (
size_t i = 0; i < wlist.
size(); ++i) {
1754 wlist[i]->process_events();
1765 void GraphicsEngine::
1767 size_t num_windows = wlist.
size();
1769 size_t warray_count = 0;
1773 for (i = 0; i < num_windows; ++i) {
1776 nassertv(warray_count < num_windows);
1777 warray[warray_count] = win;
1780 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1785 for (i = 0; i < warray_count; ++i) {
1787 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1799 void GraphicsEngine::
1801 Windows::const_iterator wi;
1802 for (wi = wlist.
begin(); wi != wlist.
end(); ++wi) {
1805 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1817 void GraphicsEngine::
1818 do_sync_frame(
Thread *current_thread) {
1822 PStatTimer timer(_sync_pcollector, current_thread);
1824 nassertv(_flip_state == FS_draw);
1828 Threads::const_iterator ti;
1829 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1830 RenderThread *thread = (*ti).second;
1831 thread->_cv_mutex.acquire();
1832 thread->_cv_mutex.release();
1835 _flip_state = FS_sync;
1844 void GraphicsEngine::
1845 do_ready_flip(
Thread *current_thread) {
1849 PStatTimer timer(_sync_pcollector, current_thread);
1851 nassertv(_flip_state == FS_draw);
1855 Threads::const_iterator ti;
1856 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1857 RenderThread *thread = (*ti).second;
1858 thread->_cv_mutex.acquire();
1859 thread->_cv_mutex.release();
1861 _app.do_ready_flip(
this,current_thread);
1862 _flip_state = FS_sync;
1871 void GraphicsEngine::
1872 do_flip_frame(
Thread *current_thread) {
1876 PStatTimer timer(_flip_pcollector, current_thread);
1878 nassertv(_flip_state == FS_draw || _flip_state == FS_sync);
1884 PStatTimer timer(_wait_pcollector, current_thread);
1885 Threads::const_iterator ti;
1886 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1887 RenderThread *thread = (*ti).second;
1888 thread->_cv_mutex.acquire();
1890 while (thread->_thread_state != TS_wait) {
1891 thread->_cv_done.wait();
1897 _app.do_flip(
this, current_thread);
1900 Threads::const_iterator ti;
1901 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1902 RenderThread *thread = (*ti).second;
1903 nassertv(thread->_thread_state == TS_wait);
1904 thread->_thread_state = TS_do_flip;
1905 thread->_cv_start.notify();
1906 thread->_cv_mutex.release();
1910 _flip_state = FS_flip;
1923 Thread *current_thread = dr->get_current_thread();
1924 PStatTimer timer(_cull_setup_pcollector, current_thread);
1939 DCAST_INTO_R(camera_node, camera.
node(), NULL);
1959 scene_root = camera.
get_top(current_thread);
1972 CPT(TransformState) camera_transform = camera.
get_transform(scene_parent, current_thread);
1973 CPT(TransformState) world_transform = scene_parent.
get_transform(camera, current_thread);
1975 if (camera_transform->is_invalid()) {
1977 if (!_singular_warning_last_frame) {
1978 display_cat.warning()
1979 <<
"Scene " << scene_root <<
" has net scale (" 1981 _singular_warning_this_frame =
true;
1986 if (world_transform->is_invalid()) {
1988 if (!_singular_warning_last_frame) {
1989 display_cat.warning()
1990 <<
"Camera " << camera <<
" has net scale (" 1993 _singular_warning_this_frame =
true;
1997 CPT(
RenderState) initial_state = camera_node->get_initial_state();
2007 initial_state = initial_state->compose(get_invert_polygon_state());
2016 scene_setup->set_initial_state(initial_state);
2023 CPT(TransformState) cs_world_transform = cs_transform->compose(world_transform);
2042 void GraphicsEngine::
2056 if (dr_reader.is_any_clear_active()) {
2057 gsg->
clear(dr_reader.get_object());
2080 if (cull_result == NULL || scene_setup == NULL) {
2091 }
else if (!gsg->
set_scene(scene_setup)) {
2094 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
2098 cull_result->
draw(current_thread);
2113 void GraphicsEngine::
2116 nassertv(window != NULL);
2123 window->_internal_sort_index = _window_sort_index;
2124 ++_window_sort_index;
2126 _windows_sorted =
false;
2129 WindowRenderer *cull =
2132 WindowRenderer *draw =
2137 cull->add_window(cull->_cull, window);
2138 draw->add_window(draw->_draw, window);
2140 cull->add_window(cull->_cdraw, window);
2154 case GraphicsPipe::PWT_app:
2155 _app.add_window(_app._window, window);
2158 case GraphicsPipe::PWT_draw:
2159 draw->add_window(draw->_window, window);
2163 if (display_cat.is_debug()) {
2165 <<
"Created " << window->get_type() <<
" " << (
void *)window <<
"\n";
2169 _needs_open_windows =
true;
2180 void GraphicsEngine::
2183 nassertv(gsg != NULL);
2187 gsg->_threading_model = threading_model;
2188 if (!_default_loader.is_null()) {
2192 auto_adjust_capabilities(gsg);
2194 WindowRenderer *draw =
2209 void GraphicsEngine::
2211 nassertv(window != NULL);
2215 if (!_windows_sorted) {
2216 do_resort_windows();
2220 _app.remove_window(window);
2221 Threads::const_iterator ti;
2222 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2223 RenderThread *thread = (*ti).second;
2224 thread->remove_window(window);
2229 _app.do_pending(
this, current_thread);
2231 if (display_cat.is_debug()) {
2233 <<
"Removed " << window->get_type() <<
" " << (
void *)window <<
"\n";
2244 void GraphicsEngine::
2245 do_resort_windows() {
2246 _windows_sorted =
true;
2248 _app.resort_windows();
2249 Threads::const_iterator ti;
2250 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2251 RenderThread *thread = (*ti).second;
2252 thread->resort_windows();
2287 void GraphicsEngine::
2318 if (textures_auto_power_2 && (textures_power_2 == ATS_none)) {
2320 <<
"Invalid panda config file: if you set the config-variable\n" 2321 <<
"textures_auto_power_2 to true, you must set the config-variable" 2322 <<
"textures_power_2 to 'up' or 'down'.\n";
2323 textures_power_2 = ATS_down;
2340 <<
"The 'textures_power_2' configuration is set to 'none', meaning \n" 2341 <<
"that non-power-of-two texture support is required, but the video \n" 2342 <<
"driver I'm trying to use does not support non-power-of-two textures.\n";
2344 if (textures_power_2 != ATS_none) {
2346 <<
"The 'none' did not come from the config file. In other words,\n" 2347 <<
"the variable 'textures_power_2' was altered procedurally.\n";
2349 if (textures_auto_power_2) {
2351 <<
"It is possible that it was set by panda's automatic mechanisms,\n" 2352 <<
"which are currently enabled, because 'textures_auto_power_2' is\n" 2353 <<
"true. Panda's automatic mechanisms assume that if one\n" 2354 <<
"window supports non-power-of-two textures, then they all will.\n" 2355 <<
"This assumption works for most games, but not all.\n" 2356 <<
"In particular, it can fail if the game creates multiple windows\n" 2357 <<
"on multiple displays with different video cards.\n";
2362 if (shader_auto_utilization && (shader_utilization != SUT_none)) {
2364 <<
"Invalid panda config file: if you set the config-variable\n" 2365 <<
"shader_auto_utilization to true, you must set the config-variable" 2366 <<
"shader_utilization to 'none'.\n";
2367 shader_utilization = SUT_none;
2384 <<
"The 'shader_utilization' config variable is set, meaning\n" 2385 <<
"that panda may try to generate shaders. However, the video \n" 2386 <<
"driver I'm trying to use does not support shaders.\n";
2388 if (shader_utilization == SUT_none) {
2390 <<
"The 'shader_utilization' setting did not come from the config\n" 2391 <<
"file. In other words, it was altered procedurally.\n";
2393 if (shader_auto_utilization) {
2395 <<
"It is possible that it was set by panda's automatic mechanisms,\n" 2396 <<
"which are currently enabled, because 'shader_auto_utilization' is\n" 2397 <<
"true. Panda's automatic mechanisms assume that if one\n" 2398 <<
"window supports shaders, then they all will.\n" 2399 <<
"This assumption works for most games, but not all.\n" 2400 <<
"In particular, it can fail if the game creates multiple windows\n" 2401 <<
"on multiple displays with different video cards.\n";
2413 void GraphicsEngine::
2414 terminate_threads(
Thread *current_thread) {
2419 PStatTimer timer(_wait_pcollector, current_thread);
2423 Threads::const_iterator ti;
2424 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2425 RenderThread *thread = (*ti).second;
2426 thread->_cv_mutex.acquire();
2430 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2431 RenderThread *thread = (*ti).second;
2432 thread->_thread_state = TS_terminate;
2433 thread->_cv_start.notify();
2434 thread->_cv_mutex.release();
2438 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2439 RenderThread *thread = (*ti).second;
2455 void GraphicsEngine::
2456 pstats_count_cycler_type(
TypeHandle type,
int count,
void *data) {
2458 CyclerTypeCounters::iterator ci =
self->_all_cycler_types.find(type);
2459 if (ci == self->_all_cycler_types.end()) {
2461 ci =
self->_all_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2463 (*ci).second.set_level(count);
2475 void GraphicsEngine::
2476 pstats_count_dirty_cycler_type(
TypeHandle type,
int count,
void *data) {
2478 CyclerTypeCounters::iterator ci =
self->_dirty_cycler_types.find(type);
2479 if (ci == self->_dirty_cycler_types.end()) {
2481 ci =
self->_dirty_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2483 (*ci).second.set_level(count);
2496 get_invert_polygon_state() {
2501 state = RenderState::make(CullFaceAttrib::make_reverse());
2519 GraphicsEngine::WindowRenderer *GraphicsEngine::
2520 get_window_renderer(
const string &name,
int pipeline_stage) {
2527 Threads::iterator ti = _threads.find(name);
2528 if (ti != _threads.end()) {
2529 return (*ti).second.p();
2532 PT(RenderThread) thread =
new RenderThread(name,
this);
2533 thread->set_min_pipeline_stage(pipeline_stage);
2536 bool started = thread->start(TP_normal,
true);
2537 nassertr(started, thread.p());
2538 _threads[name] = thread;
2540 nassertr(thread->get_pipeline_stage() < _pipeline->
get_num_stages(), thread.p());
2550 GraphicsEngine::WindowRenderer::
2551 WindowRenderer(
const string &name) :
2552 _wl_lock(
string(
"GraphicsEngine::WindowRenderer::_wl_lock ") + name)
2562 void GraphicsEngine::WindowRenderer::
2574 void GraphicsEngine::WindowRenderer::
2577 wlist.insert(window);
2588 void GraphicsEngine::WindowRenderer::
2590 nassertv(window != NULL);
2595 _cdraw.erase(ptwin);
2598 Windows::iterator wi;
2600 wi = _window.find(ptwin);
2601 if (wi != _window.end()) {
2612 if (ptwin->is_valid()) {
2613 _pending_close.push_back(ptwin);
2626 void GraphicsEngine::WindowRenderer::
2635 if (display_cat.is_debug()) {
2637 <<
"Windows resorted:";
2638 Windows::const_iterator wi;
2639 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2641 display_cat.debug(
false)
2644 display_cat.debug(
false)
2647 for (wi = _draw.begin(); wi != _draw.end(); ++wi) {
2649 display_cat.debug(
false)
2652 display_cat.debug(
false)
2665 void GraphicsEngine::WindowRenderer::
2667 PStatTimer timer(engine->_do_frame_pcollector, current_thread);
2670 engine->cull_to_bins(_cull, current_thread);
2671 engine->cull_and_draw_together(_cdraw, current_thread);
2672 engine->draw_bins(_draw, current_thread);
2673 engine->process_events(_window, current_thread);
2677 if (any_done_gsgs()) {
2680 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2685 engine->close_gsg(pipe, gsg);
2688 new_gsgs.insert(gsg);
2692 _gsgs.swap(new_gsgs);
2705 void GraphicsEngine::WindowRenderer::
2709 engine->process_events(_window, current_thread);
2711 engine->make_contexts(_cdraw, current_thread);
2712 engine->make_contexts(_draw, current_thread);
2721 void GraphicsEngine::WindowRenderer::
2724 engine->flip_windows(_cdraw, current_thread);
2725 engine->flip_windows(_draw, current_thread);
2734 void GraphicsEngine::WindowRenderer::
2737 engine->ready_flip_windows(_cdraw, current_thread);
2738 engine->ready_flip_windows(_draw, current_thread);
2747 void GraphicsEngine::WindowRenderer::
2750 Windows::iterator wi;
2751 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2759 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2764 engine->close_gsg(pipe, gsg);
2767 new_gsgs.insert(gsg);
2771 _gsgs.swap(new_gsgs);
2780 void GraphicsEngine::WindowRenderer::
2784 if (!_pending_close.empty()) {
2785 if (display_cat.is_debug()) {
2787 <<
"_pending_close.size() = " << _pending_close.size() <<
"\n";
2793 Windows::iterator wi;
2795 _pending_close.
swap(pending_close);
2796 for (wi = pending_close.
begin(); wi != pending_close.
end(); ++wi) {
2811 bool GraphicsEngine::WindowRenderer::
2812 any_done_gsgs()
const {
2813 GSGs::const_iterator gi;
2814 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2815 if ((*gi)->get_ref_count() == 1) {
2828 GraphicsEngine::RenderThread::
2831 WindowRenderer(name),
2833 _cv_mutex(
string(
"GraphicsEngine::RenderThread ") + name),
2834 _cv_start(_cv_mutex),
2837 _thread_state = TS_wait;
2847 void GraphicsEngine::RenderThread::
2853 nassertv(_cv_mutex.debug_is_locked());
2855 switch (_thread_state) {
2860 do_pending(_engine, current_thread);
2861 do_frame(_engine, current_thread);
2865 do_flip(_engine, current_thread);
2869 do_pending(_engine, current_thread);
2873 do_windows(_engine, current_thread);
2874 do_pending(_engine, current_thread);
2878 do_pending(_engine, current_thread);
2879 do_close(_engine, current_thread);
2880 _thread_state = TS_done;
2890 _thread_state = TS_wait;
2894 PStatTimer timer(_wait_pcollector, current_thread);
size_t get_total_size() const
Returns the total size of all objects currently active on the LRU.
static void flush_global_index()
If there is a global BamCache object, calls flush_index() on it.
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
void set_camera_node(Camera *camera_node)
Specifies the camera used to render the scene.
void tick(Thread *current_thread=Thread::get_current_thread())
Instructs the clock that a new frame has just begun.
int cleanup_aux_scene_data(Thread *current_thread=Thread::get_current_thread())
Walks through the list of currently-assigned AuxSceneData objects and releases any that are past thei...
virtual void request_close()
This is called by the GraphicsEngine to request that the window (or whatever) close itself or...
A basic node of the scene graph or data graph.
static void set_textures_power_2(AutoTextureScale scale)
Set this flag to ATS_none, ATS_up, ATS_down, or ATS_pad to control the scaling of textures in general...
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
GraphicsPipe * get_pipe() const
Returns the GraphicsPipe that this window is associated with.
A temporary file to hold the vertex data that has been evicted from memory and written to disk...
static SimpleLru * get_small_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that are deemed too...
static void flush_level()
Flushes the PStatCollectors used during traversal.
This is our own Panda specialization on the default STL map.
static int get_num_states()
Returns the total number of unique RenderState objects allocated in the world.
virtual GraphicsOutput * get_host()
This is normally called only from within make_texture_buffer().
void set_loader(Loader *loader)
Sets the Loader object that will be used by this GSG to load textures when necessary, if get_incomplete_render() is true.
static void set_shader_utilization(ShaderUtilization utl)
Set this flag to SUT_none, SUT_basic, or SUT_advanced to limit panda's automatic shader generation fa...
void set_display_region(DisplayRegion *display_region)
Specifies the display region for the scene.
static void flush_level()
Flushes the PStatCollectors used during traversal.
virtual void clear_before_callback()
Resets any non-standard graphics state that might give a callback apoplexy.
static bool have_shader_utilization()
If true, then get_shader_utilization has been set using set_shader_utilization.
bool is_empty() const
Returns true if there are no windows or buffers managed by the engine, false if there is at least one...
void flip_frame()
Waits for all the threads that started drawing their last frame to finish drawing, and then flips all the windows.
const NodePath & get_scene() const
Returns the scene that will be rendered by the camera.
virtual void clear(DrawableRegion *clearable)
Clears the framebuffer within the current DisplayRegion, according to the flags indicated by the give...
A base class for any number of different kinds of lenses, linear and otherwise.
GraphicsPipe * get_pipe() const
Returns the graphics pipe on which this GSG was created.
static VertexDataSaveFile * get_save_file()
Returns the global VertexDataSaveFile that will be used to save vertex data buffers to disk when nece...
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
bool is_empty() const
Returns true if the NodePath contains no nodes.
GraphicsOutput * get_window() const
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
void change_scenes(DisplayRegionPipelineReader *new_dr)
Called by the GraphicsEngine when the window is about to change to another DisplayRegion.
size_type_0 size() const
Returns the number of elements in the ordered vector.
void set_cs_world_transform(const TransformState *cs_world_transform)
Specifies the position from the starting node relative to the camera, in the GSG's internal coordinat...
void set_world_transform(const TransformState *world_transform)
Specifies the position of the starting node relative to the camera.
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
static void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup, GraphicsStateGuardian *gsg, Thread *current_thread)
Fires off a cull traversal using the indicated camera.
static void consider_flush_global_index()
If there is a global BamCache object, calls consider_flush_index() on it.
bool verify_list() const
Maps to verify_list_unique().
bool get_incomplete_render() const
Returns the incomplete_render flag.
void release_all()
Releases all prepared objects.
NodePath get_camera(Thread *current_thread=Thread::get_current_thread()) const
Returns the camera associated with this DisplayRegion, or an empty NodePath if no camera is associate...
static bool is_true_threads()
Returns true if a real threading library is available that supports actual OS-implemented threads...
virtual void dispatch_compute(int size_x, int size_y, int size_z)
Dispatches a currently bound compute shader using the given work group counts.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
void dispatch_compute(const LVecBase3i &work_groups, const ShaderAttrib *sattr, GraphicsStateGuardian *gsg)
Asks the indicated GraphicsStateGuardian to dispatch the compute shader in the given ShaderAttrib usi...
void set_cs_transform(const TransformState *cs_transform)
Specifies the transform from the camera's coordinate system to the GSG's internal coordinate system...
bool is_default() const
Returns true if the threading model is the default, cull-then-draw single-threaded model...
static void prepare_for_exit()
Should be called by the main thread just before exiting the program, this blocks until any remaining ...
void open_windows()
Fully opens (or closes) any windows that have recently been requested open or closed, without rendering any frames.
bool get_cull_sorting() const
Returns true if the model involves a separate cull pass, or false if culling happens implicitly...
ShaderGenerator * get_shader_generator() const
Returns the ShaderGenerator object that will be used by this GSG to generate shaders when necessary...
string get_name(TypedObject *object=(TypedObject *) NULL) const
Returns the name of the type.
void set_lens(const Lens *lens)
Indicates the particular Lens used for rendering.
static ShaderUtilization get_shader_utilization()
This flag returns SUT_none, SUT_basic, or SUT_advanced and controls the automatic generation of shade...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
void finish_cull(SceneSetup *scene_setup, Thread *current_thread)
Called after all the geoms have been added, this indicates that the cull process is finished for this...
virtual bool is_active() const
Returns true if the window is ready to be rendered into, false otherwise.
virtual PreferredWindowThread get_preferred_window_thread() const
Returns an indication of the thread in which this GraphicsPipe requires its window processing to be p...
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
static void flush_level()
Flushes the PStatCollectors used during traversal.
static SimpleLru * get_global_lru(RamClass rclass)
Returns a pointer to the global LRU object that manages the VertexDataPage's with the indicated RamCl...
bool remove_window(GraphicsOutput *window)
Removes the indicated window or offscreen buffer from the set of windows that will be processed when ...
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
void reserve(size_type_0 n)
Informs the vector of a planned change in size; ensures that the capacity of the vector is greater th...
A table of objects that are saved within the graphics context for reference by handle later...
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame...
static void lru_epoch()
Marks that an epoch has passed in each LRU.
This specialization on CallbackData is passed when the callback is initiated from the cull traversal...
size_t get_total_file_size() const
Returns the amount of space consumed by the save file, including unused portions. ...
const string & get_draw_name() const
Returns the name of the thread that will handle sending the actual graphics primitives to the graphic...
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
static void force_yield()
Suspends the current thread for the rest of the current epoch.
SceneSetup * get_scene_setup(Thread *current_thread) const
Returns the SceneSetup value that was stored on this DisplayRegion, presumably by the last successful...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
void ready_flip()
Waits for all the threads that started drawing their last frame to finish drawing.
void texture_uploaded(Texture *tex)
This method is called by the GraphicsStateGuardian after a texture has been successfully uploaded to ...
void set_cull_result(CullResult *cull_result, SceneSetup *scene_setup, Thread *current_thread)
Stores the result of performing a cull operation on this DisplayRegion.
void swap(ordered_vector< Key, Compare, Vector > &other)
Exchanges the contents of this vector and the other vector, in constant time (e.g., with a pointer swap).
This is a special type of PStatTimer that also uses a timer query on the GSG to measure how long a ta...
bool is_valid() const
Returns true if the output is fully created and ready for rendering, false otherwise.
PStatCollector & get_cull_region_pcollector()
Returns a PStatCollector for timing the cull operation for just this DisplayRegion.
NodePath get_camera() const
Returns the camera associated with this DisplayRegion, or an empty NodePath if no camera is associate...
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
Lens * get_lens(int index=0) const
Returns a pointer to the particular Lens associated with this LensNode, or NULL if there is not yet a...
GraphicsEngine * get_engine() const
Returns the graphics engine that created this output.
void reset_all_windows(bool swapchain)
Resets the framebuffer of the current window.
PStatCollector & get_draw_window_pcollector()
Returns a PStatCollector for timing the draw operation for just this GraphicsOutput.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
const string & get_cull_name() const
Returns the name of the thread that will handle culling in this model.
~GraphicsEngine()
Gracefully cleans up the graphics engine and its related threads and windows.
size_t get_used_file_size() const
Returns the amount of space within the save file that is currently in use.
static bool is_threading_supported()
Returns true if threading support has been compiled in and enabled, or false if no threading is avail...
A lightweight class that represents a single element that may be timed and/or counted via stats...
virtual void set_state_and_transform(const RenderState *state, const TransformState *transform)
Simultaneously resets the render state and the transform state.
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general...
virtual void do_callback(CallbackData *cbdata)
This method called when the callback is triggered; it replaces* the original function.
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
virtual void set_close_now()
This is called by the GraphicsEngine to insist that the output be closed immediately.
void cycle()
Flows all the pipeline data down to the next stage.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
CullResult * get_cull_result(Thread *current_thread) const
Returns the CullResult value that was stored on this DisplayRegion, presumably by the last successful...
virtual void clear_pipe()
Sets the window's _pipe pointer to NULL; this is generally called only as a precursor to deleting the...
virtual void request_open()
This is called by the GraphicsEngine to request that the window (or whatever) open itself or...
This special window object doesn't represent a window in its own right, but instead hooks into some t...
GraphicsOutput * get_window(int n) const
Returns the nth window or buffers managed by the engine, in sorted order.
void clear(Thread *current_thread)
Clears the entire framebuffer before rendering, according to the settings of get_color_clear_active()...
UpdateSeq get_image_modified() const
Returns a sequence number which is guaranteed to change at least every time the texture image data (i...
bool get_delete_flag() const
Returns the current setting of the delete flag.
void stop_threads()
Stops any threads that are currently running.
This defines the abstract interface for an object that receives Geoms identified by the CullTraverser...
int get_sort() const
Returns the sorting order of this particular GraphicsOutput.
int get_pixel_width(int i=0) const
Returns the width of the DisplayRegion in pixels.
This is a special GraphicsOutput type that acts a lot like a GraphicsBuffer, effectively allowing ren...
virtual void clear_state_and_transform()
Forgets the current graphics state and current transform, so that the next call to set_state_and_tran...
bool debug_is_locked() const
Returns true if the current thread has locked the ReMutex, false otherwise.
int get_cull_stage() const
Returns the pipeline stage from which the cull thread should access data.
void set_camera_path(const NodePath &camera_path)
Specifies the NodePath to the camera.
int get_frame_count(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of times tick() has been called since the ClockObject was created, or since it was last reset.
GraphicsEngine(Pipeline *pipeline=NULL)
Creates a new GraphicsEngine object.
void sync_frame()
Waits for all the threads that started drawing their last frame to finish drawing.
const NodePath & get_scene_root() const
Returns the root node of the scene.
virtual PreparedGraphicsObjects * get_prepared_objects()
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
A ClockObject keeps track of elapsed real time and discrete time.
static int get_num_unused_states()
Returns the total number of RenderState objects that have been allocated but have no references outsi...
bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg)
Asks the indicated GraphicsStateGuardian to retrieve the texture memory image of the indicated textur...
static SimpleLru * get_pending_lru()
Returns a pointer to the global LRU object that manages the VertexDataPage's that are pending process...
bool get_inverted() const
Returns the current setting of the inverted flag.
An object to create GraphicsOutputs that share a particular 3-D API.
PStatCollector & get_draw_region_pcollector()
Returns a PStatCollector for timing the draw operation for just this DisplayRegion.
bool is_single_threaded() const
Returns true if the threading model is a single-threaded model, or false if it involves threads...
void sort()
Maps to sort_unique().
static GraphicsStateGuardianBase * get_gsg(int n)
Returns the nth GSG in the universe.
The ShaderGenerator is a device that effectively replaces the classic fixed function pipeline with a ...
This CullHandler sends all of the geoms it receives into a CullResult object, for binning (and later ...
void set_camera_transform(const TransformState *camera_transform)
Specifies the position of the camera relative to the starting node.
CallbackObject * get_cull_callback() const
Returns the CallbackObject set by set_cull_callback().
bool add_window(GraphicsOutput *window, int sort)
This can be used to add a newly-created GraphicsOutput object (and its GSG) to the engine's list of w...
virtual bool is_stereo() const
Returns true if this is a StereoDisplayRegion, false otherwise.
This specialization on CallbackData is passed when the callback is initiated from the draw traversal...
Similar to MutexHolder, but for a reentrant mutex.
static Pipeline * get_render_pipeline()
Returns a pointer to the global render pipeline.
static void set_scene_root_func(SceneRootFunc *func)
This is used by the GraphicsEngine to hook in a pointer to the scene_root_func(), the function to det...
int get_draw_stage() const
Returns the pipeline stage from which the draw thread should access data.
bool get_lens_active(int index) const
Returns the active flag for the nth lens.
This is a base class for the various different classes that represent the result of a frame of render...
Similar to MutexHolder, but for a light reentrant mutex.
GraphicsOutput * make_output(GraphicsPipe *pipe, const string &name, int sort, const FrameBufferProperties &fb_prop, const WindowProperties &win_prop, int flags, GraphicsStateGuardian *gsg=NULL, GraphicsOutput *host=NULL)
Creates a new window (or buffer) and returns it.
This represents the user's specification of how a particular frame is handled by the various threads...
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
void set_scene_root(const NodePath &scene_root)
Specifies the root node of the scene.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
This class manages a staged pipeline of data, for instance the render pipeline, so that each stage of...
virtual void reset_window(bool swapchain)
Resets the window framebuffer from its derived children.
bool is_active() const
Returns the current setting of the active flag on the camera.
int get_ref_count() const
Returns the current reference count.
bool is_active() const
Returns the active flag associated with the GraphicsStateGuardian.
void remove_all_windows()
Removes and closes all windows from the engine.
void set_inverted(bool inverted)
Changes the current setting of the inverted flag.
This is a generic object that can be assigned to a callback at various points in the rendering proces...
virtual void ready_flip()
This function will be called within the draw thread after end_frame() has been called on all windows...
This is the base class for all three-component vectors and points.
void render_frame()
Renders the next frame in all the registered windows, and flips all of the frame buffers.
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins, each of which holds a number of Geoms and RenderStates to be rendered in some defined order.
static void stop_threads()
Call this to stop the paging threads, if they were started.
void set_viewport_size(int width, int height)
Specifies the size of the viewport (display region), in pixels.
static SimpleLru * get_independent_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that have not (yet)...
This special kind of CullHandler immediately draws its contents as soon as it receives them...
const NodePath & get_cull_center() const
Returns the point from which the culling operations will be performed.
bool get_timer_queries_active() const
Returns true if timer queries are currently enabled on this GSG.
GraphicsThreadingModel get_threading_model() const
Returns the threading model that will be applied to future objects.
GraphicsStateGuardian * get_gsg() const
Returns the GSG that is associated with this window.
PandaNode * node() const
Returns the referenced node of the path.
int get_num_stages() const
Returns the number of stages required for the pipeline.
A thread; that is, a lightweight process.
void set_shader_generator(ShaderGenerator *shader_generator)
Sets the ShaderGenerator object that will be used by this GSG to generate shaders when necessary...
CallbackObject * get_draw_callback() const
Returns the CallbackObject set by set_draw_callback().
virtual void begin_flip()
This function will be called within the draw thread after end_frame() has been called on all windows...
LVecBase3 get_scale() const
Retrieves the scale component of the transform.
Encapsulates all the communication with a particular instance of a given rendering backend...
bool get_supports_basic_shaders() const
Returns true if this particular GSG supports arbfp1+arbvp1 or above.
NodePath get_parent(Thread *current_thread=Thread::get_current_thread()) const
Returns the NodePath to the parent of the referenced node: that is, this NodePath, shortened by one node.
CoordinateSystem get_coordinate_system() const
Returns the coordinate system that all 3-d computations are performed within for this Lens...
static void flush_level()
Flushes the PStatCollectors used during traversal.
virtual void end_scene()
Called between begin_frame() and end_frame() to mark the end of drawing commands for a "scene" (usual...
const string & get_name() const
Returns the name that was passed to the GraphicsOutput constructor.
NodePath get_top(Thread *current_thread=Thread::get_current_thread()) const
Returns a singleton NodePath that represents the top of the path, or empty NodePath if this path is e...
static bool is_connected()
Returns true if the client believes it is connected to a working PStatServer, false otherwise...
CullTraverser * get_cull_traverser()
Returns the CullTraverser that will be used to draw the contents of this DisplayRegion.
bool is_valid() const
Returns true if the GSG has been correctly initialized within a graphics context, false if there has ...
A rectangular subregion within a window for rendering into.
void set_threading_model(const GraphicsThreadingModel &threading_model)
Specifies how future objects created via make_gsg(), make_buffer(), and make_window() will be threade...
bool needs_reset() const
Returns true if the gsg is marked as needing a reset.
int get_pixel_height(int i=0) const
Returns the height of the DisplayRegion in pixels.
int get_num_windows() const
Returns the number of windows (or buffers) managed by the engine.
void draw(Thread *current_thread)
Asks all the bins to draw themselves in the correct order.
virtual bool flip_ready() const
Returns true if a frame has been rendered and needs to be flipped, false otherwise.
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
This class is the main interface to controlling the render process.
PStatCollector & get_cull_window_pcollector()
Returns a PStatCollector for timing the cull operation for just this GraphicsOutput.
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
DisplayRegion * get_display_region() const
Returns the display region for the scene.
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
bool check_errors(Thread *current_thread)
Returns true if a clock error was detected since the last time check_errors() was called...
TypeHandle is the identifier used to differentiate C++ class types.
static bool has_textures_power_2()
If true, then get_textures_power_2 has been set using set_textures_power_2.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
This object holds the camera position, etc., and other general setup information for rendering a part...
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
bool has_size() const
Returns true if the window size has been specified, false otherwise.
bool set_scene(SceneSetup *scene_setup)
Sets the SceneSetup object that indicates the initial camera position, etc.
int get_lens_index() const
Gets the index into a lens_node lens array.
static AsyncTaskManager * get_global_ptr()
Returns a pointer to the global AsyncTaskManager.
virtual bool begin_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread before beginning rendering for a given frame...
virtual bool extract_texture_data(Texture *tex)
This method should only be called by the GraphicsEngine.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
void set_min_stages(int min_stages)
Ensures that at least the indicated number of stages are in the pipeline.
const GraphicsThreadingModel & get_threading_model() const
Returns the threading model that was used to create this GSG.
virtual bool begin_scene()
Called between begin_frame() and end_frame() to mark the beginning of drawing commands for a "scene" ...
void release_all()
Releases all prepared objects of all kinds at once.
void set_cull_handler(CullHandler *cull_handler)
Specifies the object that will receive the culled Geoms.
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
bool get_supports_tex_non_pow2() const
Returns true if this GSG can handle non power of two sized textures.