53 #define WINDOWS_LEAN_AND_MEAN 56 #undef WINDOWS_LEAN_AND_MEAN 65 PStatCollector GraphicsEngine::_wait_pcollector(
"Wait:Thread sync");
67 PStatCollector GraphicsEngine::_app_pcollector(
"App:Show code:General");
68 PStatCollector GraphicsEngine::_render_frame_pcollector(
"App:render_frame");
72 PStatCollector GraphicsEngine::_cull_setup_pcollector(
"Cull:Setup");
77 PStatCollector GraphicsEngine::_flip_begin_pcollector(
"Wait:Flip:Begin");
78 PStatCollector GraphicsEngine::_flip_end_pcollector(
"Wait:Flip:End");
79 PStatCollector GraphicsEngine::_transform_states_pcollector(
"TransformStates");
80 PStatCollector GraphicsEngine::_transform_states_unused_pcollector(
"TransformStates:Unused");
81 PStatCollector GraphicsEngine::_render_states_pcollector(
"RenderStates");
82 PStatCollector GraphicsEngine::_render_states_unused_pcollector(
"RenderStates:Unused");
83 PStatCollector GraphicsEngine::_cyclers_pcollector(
"PipelineCyclers");
84 PStatCollector GraphicsEngine::_dirty_cyclers_pcollector(
"Dirty PipelineCyclers");
88 PStatCollector GraphicsEngine::_sw_sprites_pcollector(
"SW Sprites");
89 PStatCollector GraphicsEngine::_vertex_data_small_pcollector(
"Vertex Data:Small");
90 PStatCollector GraphicsEngine::_vertex_data_independent_pcollector(
"Vertex Data:Independent");
91 PStatCollector GraphicsEngine::_vertex_data_pending_pcollector(
"Vertex Data:Pending");
92 PStatCollector GraphicsEngine::_vertex_data_resident_pcollector(
"Vertex Data:Resident");
93 PStatCollector GraphicsEngine::_vertex_data_compressed_pcollector(
"Vertex Data:Compressed");
94 PStatCollector GraphicsEngine::_vertex_data_unused_disk_pcollector(
"Vertex Data:Disk:Unused");
95 PStatCollector GraphicsEngine::_vertex_data_used_disk_pcollector(
"Vertex Data:Disk:Used");
99 PStatCollector GraphicsEngine::_cnode_volume_pcollector(
"Collision Volumes:CollisionNode");
100 PStatCollector GraphicsEngine::_gnode_volume_pcollector(
"Collision Volumes:GeomNode");
101 PStatCollector GraphicsEngine::_geom_volume_pcollector(
"Collision Volumes:Geom");
102 PStatCollector GraphicsEngine::_node_volume_pcollector(
"Collision Volumes:PandaNode");
103 PStatCollector GraphicsEngine::_volume_pcollector(
"Collision Volumes:CollisionSolid");
104 PStatCollector GraphicsEngine::_test_pcollector(
"Collision Tests:CollisionSolid");
105 PStatCollector GraphicsEngine::_volume_polygon_pcollector(
"Collision Volumes:CollisionPolygon");
106 PStatCollector GraphicsEngine::_test_polygon_pcollector(
"Collision Tests:CollisionPolygon");
107 PStatCollector GraphicsEngine::_volume_plane_pcollector(
"Collision Volumes:CollisionPlane");
108 PStatCollector GraphicsEngine::_test_plane_pcollector(
"Collision Tests:CollisionPlane");
109 PStatCollector GraphicsEngine::_volume_sphere_pcollector(
"Collision Volumes:CollisionSphere");
110 PStatCollector GraphicsEngine::_test_sphere_pcollector(
"Collision Tests:CollisionSphere");
111 PStatCollector GraphicsEngine::_volume_box_pcollector(
"Collision Volumes:CollisionBox");
112 PStatCollector GraphicsEngine::_test_box_pcollector(
"Collision Tests:CollisionBox");
113 PStatCollector GraphicsEngine::_volume_capsule_pcollector(
"Collision Volumes:CollisionCapsule");
114 PStatCollector GraphicsEngine::_test_capsule_pcollector(
"Collision Tests:CollisionCapsule");
115 PStatCollector GraphicsEngine::_volume_inv_sphere_pcollector(
"Collision Volumes:CollisionInvSphere");
116 PStatCollector GraphicsEngine::_test_inv_sphere_pcollector(
"Collision Tests:CollisionInvSphere");
117 PStatCollector GraphicsEngine::_volume_geom_pcollector(
"Collision Volumes:CollisionGeom");
118 PStatCollector GraphicsEngine::_test_geom_pcollector(
"Collision Tests:CollisionGeom");
119 PStatCollector GraphicsEngine::_occlusion_untested_pcollector(
"Occlusion results:Not tested");
120 PStatCollector GraphicsEngine::_occlusion_passed_pcollector(
"Occlusion results:Visible");
121 PStatCollector GraphicsEngine::_occlusion_failed_pcollector(
"Occlusion results:Occluded");
122 PStatCollector GraphicsEngine::_occlusion_tests_pcollector(
"Occlusion tests");
131 INLINE
static bool operator < (
const CullKey &a,
const CullKey &b) {
132 if (a._gsg != b._gsg) {
133 return a._gsg < b._gsg;
135 if (a._camera != b._camera) {
136 return a._camera < b._camera;
138 return a._lens_index < b._lens_index;
150 _lock(
"GraphicsEngine::_lock"),
151 _loaded_textures_lock(
"GraphicsEngine::_loaded_textures_lock")
153 if (_pipeline ==
nullptr) {
157 _windows_sorted =
true;
158 _window_sort_index = 0;
163 <<
"Using threading model " << _threading_model <<
"\n";
165 _auto_flip = auto_flip;
166 _portal_enabled =
false;
167 _flip_state = FS_flip;
169 _singular_warning_last_frame =
false;
170 _singular_warning_this_frame =
false;
180 if (_app_pcollector.is_started()) {
181 _app_pcollector.stop();
195 if (!Thread::is_threading_supported()) {
196 if (!threading_model.is_single_threaded()) {
197 display_cat.warning()
198 <<
"Threading model " << threading_model
199 <<
" requested but threading is not available. Ignoring.\n";
204 #ifndef THREADED_PIPELINE 205 if (!threading_model.is_single_threaded()) {
206 display_cat.warning()
207 <<
"Threading model " << threading_model
208 <<
" requested but multithreaded render pipelines not enabled in build.\n";
209 if (!allow_nonpipeline_threads) {
210 display_cat.warning()
211 <<
"Ignoring requested threading model.\n";
214 display_cat.warning()
215 <<
"Danger! Creating requested render threads anyway!\n";
217 #endif // THREADED_PIPELINE 219 _threading_model = threading_model;
227 get_threading_model()
const {
231 result = _threading_model;
254 const string &name,
int sort,
286 int x_size = 0, y_size = 0;
291 if ((x_size == 0)&&(y_size == 0)) {
292 flags |= GraphicsPipe::BF_size_track_host;
294 if (host !=
nullptr) {
302 if (host ==
nullptr) {
303 if (gsg !=
nullptr) {
312 if ((host->
get_gsg()==
nullptr)||
314 (!host->
get_gsg()->is_valid())||
315 (host->
get_gsg()->needs_reset())) {
318 if ((host->
get_gsg()==
nullptr)||
320 (!host->
get_gsg()->is_valid())||
321 (host->
get_gsg()->needs_reset())) {
331 nassertr(pipe !=
nullptr,
nullptr);
332 if (gsg !=
nullptr) {
333 nassertr(pipe == gsg->
get_pipe(),
nullptr);
338 if ((flags & GraphicsPipe::BF_require_callback_window)!=0) {
340 if (this_gsg ==
nullptr) {
343 this_gsg = pipe->make_callback_gsg(
this);
345 if (this_gsg !=
nullptr) {
347 window->_sort = sort;
348 do_add_window(window);
349 do_add_gsg(window->
get_gsg(), pipe);
350 display_cat.info() <<
"Created output of type CallbackGraphicsWindow\n";
361 bool can_use_parasite =
false;
362 if ((host !=
nullptr)&&
363 ((flags&GraphicsPipe::BF_require_window)==0)&&
364 ((flags&GraphicsPipe::BF_require_callback_window)==0)&&
365 ((flags&GraphicsPipe::BF_refuse_parasite)==0)&&
366 ((flags&GraphicsPipe::BF_can_bind_color)==0)&&
367 ((flags&GraphicsPipe::BF_can_bind_every)==0)&&
368 ((flags&GraphicsPipe::BF_rtt_cumulative)==0)&&
369 ((flags&GraphicsPipe::BF_can_bind_layered)==0)) {
370 if ((flags&GraphicsPipe::BF_fb_props_optional) ||
372 can_use_parasite =
true;
381 if ((prefer_parasite_buffer) &&
382 (can_use_parasite) &&
383 (x_size <= host->get_x_size())&&
384 (y_size <= host->get_y_size())&&
387 buffer->_sort = sort;
388 do_add_window(buffer);
389 do_add_gsg(host->
get_gsg(), pipe);
390 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
397 if (force_parasite_buffer && can_use_parasite) {
399 buffer->_sort = sort;
400 do_add_window(buffer);
401 do_add_gsg(host->
get_gsg(), pipe);
402 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
408 for (
int retry=0; retry<10; retry++) {
409 bool precertify =
false;
411 pipe->make_output(name, fb_prop, win_prop, flags,
this, gsg, host, retry, precertify);
412 if (window !=
nullptr) {
413 window->_sort = sort;
414 if (precertify && gsg !=
nullptr && window->
get_gsg() == gsg) {
415 do_add_window(window);
417 <<
"Created output of type " << window->get_type() <<
"\n";
420 do_add_window(window);
422 if (window->is_valid()) {
424 <<
"Created output of type " << window->get_type() <<
"\n";
426 if (window->get_fb_properties().subsumes(fb_prop)) {
429 if (flags & GraphicsPipe::BF_fb_props_optional) {
430 display_cat.warning()
431 <<
"FrameBufferProperties available less than requested.\n";
432 display_cat.warning(
false)
433 <<
" requested: " << fb_prop <<
"\n" 434 <<
" got: " << window->get_fb_properties() <<
"\n";
438 <<
"Could not get requested FrameBufferProperties; abandoning window.\n";
439 display_cat.error(
false)
440 <<
" requested: " << fb_prop <<
"\n" 441 <<
" got: " << window->get_fb_properties() <<
"\n";
445 << window->get_type() <<
" wouldn't open; abandoning.\n";
446 display_cat.debug(
false)
447 <<
" requested: " << fb_prop <<
"\n";
458 if (can_use_parasite) {
460 buffer->_sort = sort;
461 do_add_window(buffer);
462 do_add_gsg(host->
get_gsg(), pipe);
463 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
486 nassertr(window !=
nullptr,
false);
487 nassertr(
this == window->
get_engine(),
false);
489 window->_sort = sort;
490 do_add_window(window);
493 <<
"Added output of type " << window->get_type() <<
"\n";
517 nassertr(window !=
nullptr,
false);
518 Thread *current_thread = Thread::get_current_thread();
525 if (!_windows_sorted) {
528 count = _windows.erase(ptwin);
533 MutexHolder new_windows_holder(_new_windows_lock, current_thread);
534 size_t old_size = _new_windows.size();
535 _new_windows.erase(std::remove(_new_windows.begin(), _new_windows.end(), ptwin), _new_windows.end());
536 if (count == 0 && _new_windows.size() < old_size) {
546 do_remove_window(window, current_thread);
549 if (gsg !=
nullptr) {
551 if (pgo !=
nullptr) {
553 bool any_common =
false;
556 Windows::iterator wi;
557 for (wi = _windows.
begin(); wi != _windows.
end() && !any_common; ++wi) {
559 if (gsg2 !=
nullptr &&
576 nassertr(count == 1,
true);
586 Thread *current_thread = Thread::get_current_thread();
595 old_windows.
swap(_windows);
596 Windows::iterator wi;
598 nassertv(win !=
nullptr);
599 do_remove_window(win, current_thread);
601 if (gsg !=
nullptr) {
607 MutexHolder new_windows_holder(_new_windows_lock, current_thread);
609 nassertv(win !=
nullptr);
610 do_remove_window(win, current_thread);
612 if (gsg !=
nullptr) {
616 _new_windows.clear();
619 _app.do_close(
this, current_thread);
620 _app.do_pending(
this, current_thread);
621 terminate_threads(current_thread);
638 PStatClient::get_global_pstats()->disconnect();
652 Windows::iterator wi;
653 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
666 return _windows.
empty();
673 get_num_windows()
const {
674 return _windows.
size();
682 nassertr(n >= 0 && n < (
int)_windows.
size(),
nullptr);
684 if (!_windows_sorted) {
696 Thread *current_thread = Thread::get_current_thread();
706 _render_frame_pcollector.start();
707 if (_app_pcollector.is_started()) {
708 _app_pcollector.stop();
721 if (display_cat.is_spam()) {
723 <<
"render_frame() - frame " << global_clock->
get_frame_count() <<
"\n";
729 if (!_windows_sorted) {
733 if (sync_flip && _flip_state != FS_flip) {
734 do_flip_frame(current_thread);
740 Windows::iterator wi;
741 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
743 nassertv(win !=
nullptr);
745 do_remove_window(win, current_thread);
755 int num_drs = win->get_num_active_display_regions();
756 for (
int i = 0; i < num_drs; ++i) {
763 if (scene.is_empty()) {
764 scene = camera_np.
get_top(current_thread);
766 if (!scene.is_empty()) {
767 scene.get_bounds(current_thread);
774 _windows.
swap(new_windows);
780 LoadedTextures::iterator lti;
781 for (lti = _loaded_textures.begin(); lti != _loaded_textures.end(); ++lti) {
782 LoadedTexture < = (*lti);
783 if (lt._tex->get_image_modified() == lt._image_modified) {
784 lt._tex->texture_uploaded();
787 _loaded_textures.clear();
792 _app.do_frame(
this, current_thread);
797 PStatTimer timer(_wait_pcollector, current_thread);
798 Threads::const_iterator ti;
799 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
800 RenderThread *thread = (*ti).second;
801 thread->_cv_mutex.acquire();
803 while (thread->_thread_state != TS_wait) {
804 thread->_cv_done.wait();
809 #if defined(THREADED_PIPELINE) && defined(DO_PSTATS) 810 _cyclers_pcollector.set_level(_pipeline->get_num_cyclers());
811 _dirty_cyclers_pcollector.set_level(_pipeline->get_num_dirty_cyclers());
815 _pipeline->iterate_all_cycler_types(pstats_count_cycler_type,
this);
816 _pipeline->iterate_dirty_cycler_types(pstats_count_dirty_cycler_type,
this);
818 #endif // DEBUG_THREADS 820 #endif // THREADED_PIPELINE && DO_PSTATS 825 TransformState::flush_level();
829 #ifdef THREADED_PIPELINE 831 PStatTimer timer(_cycle_pcollector, current_thread);
834 #endif // THREADED_PIPELINE 836 global_clock->
tick(current_thread);
838 throw_event(
"clock_error");
842 PStatClient::main_tick();
845 CullTraverser::_nodes_pcollector.clear_level();
846 CullTraverser::_geom_nodes_pcollector.clear_level();
847 CullTraverser::_geoms_pcollector.clear_level();
848 GeomCacheManager::_geom_cache_active_pcollector.clear_level();
849 GeomCacheManager::_geom_cache_record_pcollector.clear_level();
850 GeomCacheManager::_geom_cache_erase_pcollector.clear_level();
851 GeomCacheManager::_geom_cache_evict_pcollector.clear_level();
853 GraphicsStateGuardian::init_frame_pstats();
855 _transform_states_pcollector.set_level(TransformState::get_num_states());
857 if (pstats_unused_states) {
858 _transform_states_unused_pcollector.set_level(TransformState::get_num_unused_states());
862 _sw_sprites_pcollector.clear_level();
864 _cnode_volume_pcollector.clear_level();
865 _gnode_volume_pcollector.clear_level();
866 _geom_volume_pcollector.clear_level();
867 _node_volume_pcollector.clear_level();
868 _volume_pcollector.clear_level();
869 _test_pcollector.clear_level();
870 _volume_polygon_pcollector.clear_level();
871 _test_polygon_pcollector.clear_level();
872 _volume_plane_pcollector.clear_level();
873 _test_plane_pcollector.clear_level();
874 _volume_sphere_pcollector.clear_level();
875 _test_sphere_pcollector.clear_level();
876 _volume_box_pcollector.clear_level();
877 _test_box_pcollector.clear_level();
878 _volume_capsule_pcollector.clear_level();
879 _test_capsule_pcollector.clear_level();
880 _volume_inv_sphere_pcollector.clear_level();
881 _test_inv_sphere_pcollector.clear_level();
882 _volume_geom_pcollector.clear_level();
883 _test_geom_pcollector.clear_level();
884 _occlusion_untested_pcollector.clear_level();
885 _occlusion_passed_pcollector.clear_level();
886 _occlusion_failed_pcollector.clear_level();
887 _occlusion_tests_pcollector.clear_level();
900 _vertex_data_small_pcollector.set_level(small_buf);
901 _vertex_data_independent_pcollector.set_level(independent);
902 _vertex_data_pending_pcollector.set_level(pending);
903 _vertex_data_resident_pcollector.set_level(resident);
904 _vertex_data_compressed_pcollector.set_level(compressed);
905 _vertex_data_unused_disk_pcollector.set_level(total_disk - used_disk);
906 _vertex_data_used_disk_pcollector.set_level(used_disk);
914 Threads::const_iterator ti;
915 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
916 RenderThread *thread = (*ti).second;
917 if (thread->_thread_state == TS_wait) {
918 thread->_thread_state = TS_do_frame;
919 thread->_cv_start.notify();
921 thread->_cv_mutex.release();
926 _flip_state = _auto_flip ? FS_flip : FS_draw;
931 if (yield_timeslice) {
934 PStatTimer timer(_yield_pcollector, current_thread);
936 }
else if (!Thread::is_true_threads()) {
937 PStatTimer timer(_yield_pcollector, current_thread);
943 _app_pcollector.start();
944 _render_frame_pcollector.stop();
957 Thread *current_thread = Thread::get_current_thread();
963 MutexHolder new_windows_holder(_new_windows_lock, current_thread);
964 if (_new_windows.empty()) {
968 for (
auto it = _new_windows.begin(); it != _new_windows.end(); ++it) {
971 WindowRenderer *cull =
974 WindowRenderer *draw =
979 cull->add_window(cull->_cull, window);
980 draw->add_window(draw->_draw, window);
982 cull->add_window(cull->_cdraw, window);
994 switch (window->
get_pipe()->get_preferred_window_thread()) {
995 case GraphicsPipe::PWT_app:
996 _app.add_window(_app._window, window);
999 case GraphicsPipe::PWT_draw:
1000 draw->add_window(draw->_window, window);
1008 new_windows.swap(_new_windows);
1011 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();
1035 for (
auto it = new_windows.begin(); it != new_windows.end(); ++it) {
1053 Thread *current_thread = Thread::get_current_thread();
1056 if (_flip_state == FS_draw) {
1057 do_sync_frame(current_thread);
1074 Thread *current_thread = Thread::get_current_thread();
1077 if (_flip_state == FS_draw) {
1078 do_ready_flip(current_thread);
1089 Thread *current_thread = Thread::get_current_thread();
1092 if (_flip_state != FS_flip) {
1093 do_flip_frame(current_thread);
1123 if (draw_name.empty()) {
1130 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1131 RenderThread *thread = (RenderThread *)wr;
1134 while (thread->_thread_state != TS_wait) {
1135 thread->_cv_done.wait();
1139 int pipeline_stage = Thread::get_current_pipeline_stage();
1140 int draw_pipeline_stage = thread->get_pipeline_stage();
1141 thread->set_pipeline_stage(pipeline_stage);
1145 thread->_texture = tex;
1146 thread->_thread_state = TS_do_extract;
1147 thread->_cv_start.notify();
1148 thread->_cv_mutex.release();
1149 thread->_cv_mutex.acquire();
1152 while (thread->_thread_state != TS_wait) {
1153 thread->_cv_done.wait();
1156 thread->set_pipeline_stage(draw_pipeline_stage);
1157 thread->_gsg =
nullptr;
1158 thread->_texture =
nullptr;
1159 return thread->_result;
1178 const Shader *shader = sattr->get_shader();
1179 nassertv(shader !=
nullptr);
1180 nassertv(gsg !=
nullptr);
1184 CPT(
RenderState) state = RenderState::make(sattr);
1187 if (draw_name.empty()) {
1192 gsg->pop_group_marker();
1197 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1198 RenderThread *thread = (RenderThread *)wr;
1201 while (thread->_thread_state != TS_wait) {
1202 thread->_cv_done.wait();
1206 int pipeline_stage = Thread::get_current_pipeline_stage();
1207 int draw_pipeline_stage = thread->get_pipeline_stage();
1208 thread->set_pipeline_stage(pipeline_stage);
1212 thread->_state = state.p();
1213 thread->_work_groups = work_groups;
1214 thread->_thread_state = TS_do_compute;
1215 thread->_cv_start.notify();
1216 thread->_cv_mutex.release();
1217 thread->_cv_mutex.acquire();
1220 while (thread->_thread_state != TS_wait) {
1221 thread->_cv_done.wait();
1224 thread->set_pipeline_stage(draw_pipeline_stage);
1225 thread->_gsg =
nullptr;
1226 thread->_state =
nullptr;
1235 if (_global_ptr ==
nullptr) {
1256 _loaded_textures.push_back(LoadedTexture());
1257 LoadedTexture < = _loaded_textures.back();
1274 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1275 RenderThread *thread = (RenderThread *)wr;
1278 while (thread->_thread_state != TS_wait) {
1279 thread->_cv_done.wait();
1283 thread->_region = region;
1284 thread->_thread_state = TS_do_screenshot;
1285 thread->_cv_start.notify();
1286 thread->_cv_mutex.release();
1287 thread->_cv_mutex.acquire();
1290 while (thread->_thread_state != TS_wait) {
1291 thread->_cv_done.wait();
1294 PT(
Texture) tex = std::move(thread->_texture);
1295 thread->_region =
nullptr;
1296 thread->_texture =
nullptr;
1310 trav->set_cull_handler(cull_handler);
1313 trav->set_view_frustum(
nullptr);
1314 if (view_frustum_cull) {
1322 if (bv !=
nullptr && !bv->is_infinite() &&
1323 bv->as_geometric_bounding_volume() !=
nullptr) {
1326 local_frustum = bv->make_copy()->as_geometric_bounding_volume();
1327 nassertv(!local_frustum.is_null());
1332 local_frustum->xform(cull_center_transform->get_mat());
1334 trav->set_view_frustum(local_frustum);
1339 trav->end_traverse();
1347 bool GraphicsEngine::
1348 scene_root_func(
const PandaNode *node) {
1349 return _global_ptr->is_scene_root(node);
1356 bool GraphicsEngine::
1360 Windows::const_iterator wi;
1361 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
1364 int num_display_regions = win->get_num_active_display_regions();
1365 for (
int i = 0; i < num_display_regions; i++) {
1367 if (dr !=
nullptr) {
1374 DCAST_INTO_R(camera_node, camera.
node(),
false);
1384 scene_root = camera.
get_top(current_thread);
1387 if (scene_root.
node() == node) {
1404 void GraphicsEngine::
1407 window->_sort = sort;
1408 _windows_sorted =
false;
1417 void GraphicsEngine::
1419 Thread *current_thread) {
1420 PStatTimer timer(_cull_pcollector, current_thread);
1422 size_t wlist_size = wlist.
size();
1423 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1428 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1432 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1437 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1441 gsg->push_group_marker(
"Clear");
1442 win->
clear(current_thread);
1443 gsg->pop_group_marker();
1446 int num_display_regions = win->get_num_active_display_regions();
1447 for (
int i = 0; i < num_display_regions; i++) {
1449 if (dr !=
nullptr) {
1450 cull_and_draw_together(win, dr, current_thread);
1453 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1458 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1462 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1475 void GraphicsEngine::
1477 Thread *current_thread) {
1479 nassertv(gsg !=
nullptr);
1490 if (dr_reader.is_any_clear_active()) {
1495 scene_setup = setup_scene(gsg, &dr_reader);
1498 if (scene_setup ==
nullptr) {
1504 }
else if (!gsg->
set_scene(scene_setup)) {
1507 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
1513 if (cbobj !=
nullptr) {
1522 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1529 gsg->pop_group_marker();
1537 void GraphicsEngine::
1539 PStatTimer timer(_cull_pcollector, current_thread);
1541 _singular_warning_last_frame = _singular_warning_this_frame;
1542 _singular_warning_this_frame =
false;
1547 AlreadyCulled already_culled;
1549 size_t wlist_size = wlist.
size();
1550 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1555 int num_display_regions = win->get_num_active_display_regions();
1556 for (
int i = 0; i < num_display_regions; ++i) {
1558 if (dr !=
nullptr) {
1563 PStatTimer timer(_cull_setup_pcollector, current_thread);
1565 scene_setup = setup_scene(gsg, &dr_reader);
1566 if (scene_setup ==
nullptr) {
1571 key._camera = dr_reader.get_camera();
1572 key._lens_index = dr_reader.get_lens_index();
1575 AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(std::move(key),
nullptr)).first;
1576 if ((*aci).second ==
nullptr) {
1580 if (cull_result !=
nullptr) {
1581 cull_result = cull_result->make_next();
1587 cull_to_bins(win, gsg, dr, scene_setup, cull_result, current_thread);
1601 dr->
set_cull_result(std::move(cull_result), MOVE(scene_setup), current_thread);
1611 void GraphicsEngine::
1618 if (cbobj !=
nullptr) {
1627 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1630 PStatTimer timer(_cull_sort_pcollector, current_thread);
1631 cull_result->
finish_cull(scene_setup, current_thread);
1639 void GraphicsEngine::
1643 size_t wlist_size = wlist.
size();
1644 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1655 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1659 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1664 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1671 win->
get_gsg()->push_group_marker(
"Clear");
1672 win->
clear(current_thread);
1673 win->
get_gsg()->pop_group_marker();
1676 if (display_cat.is_spam()) {
1678 <<
"Drawing window " << win->
get_name() <<
"\n";
1680 int num_display_regions = win->get_num_active_display_regions();
1681 for (
int i = 0; i < num_display_regions; ++i) {
1683 if (dr !=
nullptr) {
1684 do_draw(win, gsg, dr, current_thread);
1688 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1694 gsg->issue_timer_query(GraphicsStateGuardian::_command_latency_pcollector.get_index());
1702 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1706 PStatGPUTimer timer(gsg, GraphicsEngine::_flip_end_pcollector, current_thread);
1713 if (display_cat.is_spam()) {
1715 <<
"Not drawing window " << win->
get_name() <<
"\n";
1720 if (display_cat.is_spam()) {
1722 <<
"Window " << win->
get_name() <<
" is inactive\n";
1732 void GraphicsEngine::
1734 Windows::const_iterator wi;
1735 for (wi = wlist.
begin(); wi != wlist.
end(); ++wi) {
1737 if (win->
begin_frame(GraphicsOutput::FM_refresh, current_thread)) {
1738 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();
1763 void GraphicsEngine::
1765 size_t num_windows = wlist.
size();
1767 size_t warray_count = 0;
1771 for (i = 0; i < num_windows; ++i) {
1774 nassertv(warray_count < num_windows);
1775 warray[warray_count] = win;
1778 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1783 for (i = 0; i < warray_count; ++i) {
1785 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1795 void GraphicsEngine::
1797 Windows::const_iterator wi;
1798 for (wi = wlist.
begin(); wi != wlist.
end(); ++wi) {
1801 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1811 void GraphicsEngine::
1812 do_sync_frame(
Thread *current_thread) {
1816 PStatTimer timer(_sync_pcollector, current_thread);
1818 nassertv(_flip_state == FS_draw);
1822 Threads::const_iterator ti;
1823 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1824 RenderThread *thread = (*ti).second;
1825 thread->_cv_mutex.acquire();
1826 thread->_cv_mutex.release();
1829 _flip_state = FS_sync;
1836 void GraphicsEngine::
1837 do_ready_flip(
Thread *current_thread) {
1841 PStatTimer timer(_sync_pcollector, current_thread);
1843 nassertv(_flip_state == FS_draw);
1847 Threads::const_iterator ti;
1848 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1849 RenderThread *thread = (*ti).second;
1850 thread->_cv_mutex.acquire();
1851 thread->_cv_mutex.release();
1853 _app.do_ready_flip(
this,current_thread);
1854 _flip_state = FS_sync;
1861 void GraphicsEngine::
1862 do_flip_frame(
Thread *current_thread) {
1866 PStatTimer timer(_flip_pcollector, current_thread);
1868 nassertv(_flip_state == FS_draw || _flip_state == FS_sync);
1874 PStatTimer timer(_wait_pcollector, current_thread);
1875 Threads::const_iterator ti;
1876 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1877 RenderThread *thread = (*ti).second;
1878 thread->_cv_mutex.acquire();
1880 while (thread->_thread_state != TS_wait) {
1881 thread->_cv_done.wait();
1887 _app.do_flip(
this, current_thread);
1890 Threads::const_iterator ti;
1891 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1892 RenderThread *thread = (*ti).second;
1893 nassertv(thread->_thread_state == TS_wait);
1894 thread->_thread_state = TS_do_flip;
1895 thread->_cv_start.notify();
1896 thread->_cv_mutex.release();
1900 _flip_state = FS_flip;
1910 Thread *current_thread = dr->get_current_thread();
1911 PStatTimer timer(_cull_setup_pcollector, current_thread);
1916 nassertr(window !=
nullptr,
nullptr);
1925 DCAST_INTO_R(camera_node, camera.
node(),
nullptr);
1945 scene_root = camera.
get_top(current_thread);
1961 if (camera_transform->is_invalid()) {
1963 if (!_singular_warning_last_frame) {
1964 display_cat.warning()
1965 <<
"Scene " << scene_root <<
" has net scale (" 1967 _singular_warning_this_frame =
true;
1972 if (world_transform->is_invalid()) {
1974 if (!_singular_warning_last_frame) {
1975 display_cat.warning()
1976 <<
"Camera " << camera <<
" has net scale (" 1979 _singular_warning_this_frame =
true;
1983 CPT(
RenderState) initial_state = camera_node->get_initial_state();
1993 initial_state = initial_state->compose(get_invert_polygon_state());
2002 scene_setup->set_initial_state(initial_state);
2009 CPT(
TransformState) cs_world_transform = cs_transform->compose(world_transform);
2018 void GraphicsEngine::
2029 cull_result = cdata->_cull_result;
2030 scene_setup = cdata->_scene_setup;
2039 if (dr_reader.is_any_clear_active()) {
2041 gsg->
clear(dr_reader.get_object());
2044 cbobj = dr_reader.get_draw_callback();
2047 if (cbobj !=
nullptr) {
2052 static CPT(
RenderState) state = RenderState::make(
2053 DepthTestAttrib::make(DepthTestAttrib::M_none));
2063 }
else if (cull_result ==
nullptr || scene_setup ==
nullptr) {
2073 }
else if (!gsg->
set_scene(scene_setup)) {
2076 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
2080 cull_result->
draw(current_thread);
2085 gsg->pop_group_marker();
2093 void GraphicsEngine::
2095 nassertv(window !=
nullptr);
2102 window->_internal_sort_index = _window_sort_index;
2103 ++_window_sort_index;
2105 if (display_cat.is_debug()) {
2107 <<
"Created " << window->get_type() <<
" " << (
void *)window <<
"\n";
2111 _new_windows.push_back(window);
2119 void GraphicsEngine::
2121 nassertv(gsg !=
nullptr);
2125 gsg->_threading_model = _threading_model;
2126 if (!_default_loader.is_null()) {
2130 auto_adjust_capabilities(gsg);
2132 WindowRenderer *draw =
2144 void GraphicsEngine::
2146 nassertv(window !=
nullptr);
2150 if (!_windows_sorted) {
2151 do_resort_windows();
2155 _app.remove_window(window);
2156 Threads::const_iterator ti;
2157 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2158 RenderThread *thread = (*ti).second;
2159 thread->remove_window(window);
2164 _app.do_pending(
this, current_thread);
2166 if (display_cat.is_debug()) {
2168 <<
"Removed " << window->get_type() <<
" " << (
void *)window <<
"\n";
2176 void GraphicsEngine::
2177 do_resort_windows() {
2178 _windows_sorted =
true;
2180 _app.resort_windows();
2181 Threads::const_iterator ti;
2182 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2183 RenderThread *thread = (*ti).second;
2184 thread->resort_windows();
2210 void GraphicsEngine::
2232 if (textures_auto_power_2 && (textures_power_2 == ATS_none)) {
2234 <<
"Invalid panda config file: if you set the config-variable\n" 2235 <<
"textures_auto_power_2 to true, you must set the config-variable" 2236 <<
"textures_power_2 to 'up' or 'down'.\n";
2237 textures_power_2 = ATS_down;
2254 <<
"The 'textures_power_2' configuration is set to 'none', meaning \n" 2255 <<
"that non-power-of-two texture support is required, but the video \n" 2256 <<
"driver I'm trying to use does not support non-power-of-two textures.\n";
2258 if (textures_power_2 != ATS_none) {
2260 <<
"The 'none' did not come from the config file. In other words,\n" 2261 <<
"the variable 'textures_power_2' was altered procedurally.\n";
2263 if (textures_auto_power_2) {
2265 <<
"It is possible that it was set by panda's automatic mechanisms,\n" 2266 <<
"which are currently enabled, because 'textures_auto_power_2' is\n" 2267 <<
"true. Panda's automatic mechanisms assume that if one\n" 2268 <<
"window supports non-power-of-two textures, then they all will.\n" 2269 <<
"This assumption works for most games, but not all.\n" 2270 <<
"In particular, it can fail if the game creates multiple windows\n" 2271 <<
"on multiple displays with different video cards.\n";
2280 void GraphicsEngine::
2281 terminate_threads(
Thread *current_thread) {
2286 PStatTimer timer(_wait_pcollector, current_thread);
2290 Threads::const_iterator ti;
2291 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2292 RenderThread *thread = (*ti).second;
2293 thread->_cv_mutex.acquire();
2297 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2298 RenderThread *thread = (*ti).second;
2299 thread->_thread_state = TS_terminate;
2300 thread->_cv_start.notify();
2301 thread->_cv_mutex.release();
2305 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2306 RenderThread *thread = (*ti).second;
2319 void GraphicsEngine::
2320 pstats_count_cycler_type(
TypeHandle type,
int count,
void *data) {
2322 CyclerTypeCounters::iterator ci =
self->_all_cycler_types.find(type);
2323 if (ci == self->_all_cycler_types.end()) {
2325 ci =
self->_all_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2327 (*ci).second.set_level(count);
2336 void GraphicsEngine::
2337 pstats_count_dirty_cycler_type(
TypeHandle type,
int count,
void *data) {
2339 CyclerTypeCounters::iterator ci =
self->_dirty_cycler_types.find(type);
2340 if (ci == self->_dirty_cycler_types.end()) {
2342 ci =
self->_dirty_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2344 (*ci).second.set_level(count);
2354 get_invert_polygon_state() {
2358 if (state ==
nullptr) {
2359 state = RenderState::make(CullFaceAttrib::make_reverse());
2373 GraphicsEngine::WindowRenderer *GraphicsEngine::
2374 get_window_renderer(
const string &name,
int pipeline_stage) {
2381 Threads::iterator ti = _threads.find(name);
2382 if (ti != _threads.end()) {
2383 return (*ti).second.p();
2386 PT(RenderThread) thread =
new RenderThread(name,
this);
2387 thread->set_min_pipeline_stage(pipeline_stage);
2390 bool started = thread->start(TP_normal,
true);
2391 nassertr(started, thread.p());
2392 _threads[name] = thread;
2394 nassertr(thread->get_pipeline_stage() < _pipeline->
get_num_stages(), thread.p());
2402 GraphicsEngine::WindowRenderer::
2403 WindowRenderer(
const string &name) :
2404 _wl_lock(string(
"GraphicsEngine::WindowRenderer::_wl_lock ") + name)
2411 void GraphicsEngine::WindowRenderer::
2421 void GraphicsEngine::WindowRenderer::
2424 wlist.insert(window);
2432 void GraphicsEngine::WindowRenderer::
2434 nassertv(window !=
nullptr);
2439 _cdraw.erase(ptwin);
2442 Windows::iterator wi;
2444 wi = _window.find(ptwin);
2445 if (wi != _window.end()) {
2455 if (ptwin->is_valid()) {
2456 _pending_close.push_back(ptwin);
2466 void GraphicsEngine::WindowRenderer::
2475 if (display_cat.is_debug()) {
2477 <<
"Windows resorted:";
2478 Windows::const_iterator wi;
2479 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2481 display_cat.debug(
false)
2484 display_cat.debug(
false)
2487 for (wi = _draw.begin(); wi != _draw.end(); ++wi) {
2489 display_cat.debug(
false)
2492 display_cat.debug(
false)
2502 void GraphicsEngine::WindowRenderer::
2504 PStatTimer timer(engine->_do_frame_pcollector, current_thread);
2507 engine->cull_to_bins(_cull, current_thread);
2508 engine->cull_and_draw_together(_cdraw, current_thread);
2509 engine->draw_bins(_draw, current_thread);
2510 engine->process_events(_window, current_thread);
2514 if (any_done_gsgs()) {
2517 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2522 engine->close_gsg(pipe, gsg);
2525 new_gsgs.insert(gsg);
2529 _gsgs.swap(new_gsgs);
2539 void GraphicsEngine::WindowRenderer::
2543 engine->process_events(_window, current_thread);
2545 engine->make_contexts(_cdraw, current_thread);
2546 engine->make_contexts(_draw, current_thread);
2552 void GraphicsEngine::WindowRenderer::
2555 engine->flip_windows(_cdraw, current_thread);
2556 engine->flip_windows(_draw, current_thread);
2562 void GraphicsEngine::WindowRenderer::
2565 engine->ready_flip_windows(_cdraw, current_thread);
2566 engine->ready_flip_windows(_draw, current_thread);
2573 void GraphicsEngine::WindowRenderer::
2576 Windows::iterator wi;
2577 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2585 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2590 engine->close_gsg(pipe, gsg);
2593 new_gsgs.insert(gsg);
2597 _gsgs.swap(new_gsgs);
2604 void GraphicsEngine::WindowRenderer::
2608 if (!_pending_close.empty()) {
2609 if (display_cat.is_debug()) {
2611 <<
"_pending_close.size() = " << _pending_close.size() <<
"\n";
2617 Windows::iterator wi;
2618 Windows pending_close;
2619 _pending_close.swap(pending_close);
2620 for (wi = pending_close.begin(); wi != pending_close.end(); ++wi) {
2632 bool GraphicsEngine::WindowRenderer::
2633 any_done_gsgs()
const {
2634 GSGs::const_iterator gi;
2635 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2636 if ((*gi)->get_ref_count() == 1) {
2647 GraphicsEngine::RenderThread::
2650 WindowRenderer(name),
2652 _cv_mutex(string(
"GraphicsEngine::RenderThread ") + name),
2653 _cv_start(_cv_mutex),
2656 _thread_state = TS_wait;
2663 void GraphicsEngine::RenderThread::
2669 nassertv(_cv_mutex.debug_is_locked());
2671 switch (_thread_state) {
2676 do_pending(_engine, current_thread);
2677 do_frame(_engine, current_thread);
2681 do_flip(_engine, current_thread);
2685 do_pending(_engine, current_thread);
2689 do_windows(_engine, current_thread);
2690 do_pending(_engine, current_thread);
2694 nassertd(_gsg !=
nullptr && _state !=
nullptr) break;
2697 _state->get_attrib(sattr);
2698 _gsg->push_group_marker(std::string(
"Compute ") + sattr->get_shader()->get_filename(Shader::ST_compute).get_basename());
2699 _gsg->set_state_and_transform(_state, TransformState::make_identity());
2700 _gsg->dispatch_compute(_work_groups[0], _work_groups[1], _work_groups[2]);
2701 _gsg->pop_group_marker();
2706 nassertd(_gsg !=
nullptr && _texture !=
nullptr) break;
2707 _result = _gsg->extract_texture_data(_texture);
2710 case TS_do_screenshot:
2711 nassertd(_region !=
nullptr) break;
2712 _texture = _region->get_screenshot();
2716 do_pending(_engine, current_thread);
2717 do_close(_engine, current_thread);
2718 _thread_state = TS_done;
2728 _thread_state = TS_wait;
2732 PStatTimer timer(_wait_pcollector, current_thread);
size_t get_total_size() const
Returns the total size of all objects currently active on the LRU.
set_scene
Sets the SceneSetup object that indicates the initial camera position, etc.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
get_ref_count
Returns the current reference count.
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...
void set_cull_result(PT(CullResult) cull_result, PT(SceneSetup) scene_setup, Thread *current_thread)
Stores the result of performing a cull operation on this DisplayRegion.
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
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_display_region(DisplayRegion *display_region)
Specifies the display region for the scene.
static void flush_level()
Flushes the PStatCollectors used during traversal.
get_pipe
Returns the graphics pipe on which this GSG was created.
virtual void clear_before_callback()
Resets any non-standard graphics state that might give a callback apoplexy.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_cull_traverser
Returns the CullTraverser that will be used to draw the contents of this DisplayRegion.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
get_supports_tex_non_pow2
Returns true if this GSG can handle non power of two sized textures.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_gsg
Returns the nth GSG in the universe.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
is_active
Returns true if the window is ready to be rendered into, false otherwise.
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.
get_sort
Returns the sorting order of this particular GraphicsOutput.
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().
void release_all()
Releases all prepared objects.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_window
Returns the nth window or buffers managed by the engine, in sorted order.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsEngine(Pipeline *pipeline=nullptr)
Creates a new GraphicsEngine object.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename get_filename(ShaderType type=ST_none) const
Return the Shader's filename for the given shader type.
void set_lens(const Lens *lens)
Indicates the particular Lens used for rendering.
get_parent
Returns the NodePath to the parent of the referenced node: that is, this NodePath, shortened by one node.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
is_stereo
Returns true if this is a StereoDisplayRegion, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
set_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 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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(Texture) GraphicsEngine
Called by DisplayRegion::do_get_screenshot.
PStatCollector & get_clear_window_pcollector()
Returns a PStatCollector for timing the clear operation for just this GraphicsOutput.
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. ...
is_active
Returns the current setting of the active flag on the camera.
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.
get_name
Returns the name of the type.
get_engine
Returns the graphics engine that created this output.
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 ...
GraphicsOutput * make_output(GraphicsPipe *pipe, const std::string &name, int sort, const FrameBufferProperties &fb_prop, const WindowProperties &win_prop, int flags, GraphicsStateGuardian *gsg=nullptr, GraphicsOutput *host=nullptr)
Creates a new window (or buffer) and returns it.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
~GraphicsEngine()
Gracefully cleans up the graphics engine and its related threads and windows.
get_cull_callback
Returns the CallbackObject set by set_cull_callback().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
size_t get_used_file_size() const
Returns the amount of space within the save file that is currently in use.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void cycle()
Flows all the pipeline data down to the next stage.
get_current_thread
Returns a pointer to the currently-executing Thread object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
virtual void clear(Thread *current_thread)
Clears the entire framebuffer before rendering, according to the settings of get_color_clear_active()...
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_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...
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created, or since it was last reset.
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.
const std::string & get_cull_name() const
Returns the name of the thread that will handle culling in this model.
void set_camera_path(const NodePath &camera_path)
Specifies the NodePath to the camera.
void sync_frame()
Waits for all the threads that started drawing their last frame to finish drawing.
is_valid
Returns true if the GSG has been correctly initialized within a graphics context, false if there has ...
const NodePath & get_scene_root() const
Returns the root node of the scene.
get_pipe
Returns the GraphicsPipe that this window is associated with.
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...
An object to create GraphicsOutputs that share a particular 3-D API.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PStatCollector & get_draw_region_pcollector()
Returns a PStatCollector for timing the draw operation for just this DisplayRegion.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void sort()
Maps to sort_unique().
get_scene
Returns the scene that will be rendered by the camera.
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.
get_timer_queries_active
Returns true if timer queries are currently enabled on this GSG.
set_threading_model
Specifies how future objects created via make_gsg(), make_buffer(), and make_window() will be threade...
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
get_incomplete_render
Returns the incomplete_render flag.
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.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_basename() const
Returns the basename part of the filename.
virtual void reset_window(bool swapchain)
Resets the window framebuffer from its derived children.
const std::string & get_draw_name() const
Returns the name of the thread that will handle sending the actual graphics primitives to the graphic...
get_inverted
Returns the current setting of the inverted flag.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void ready_flip()
This function will be called within the draw thread after end_frame() has been called on all windows...
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)...
virtual bool is_any_clear_active() const
Returns true if any of the clear types (so far there are just color or depth) have been set active...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
get_name
Returns the name that was passed to the GraphicsOutput constructor.
PandaNode * node() const
Returns the referenced node of the path.
int get_num_stages() const
Returns the number of stages required for the pipeline.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
const std::string & get_debug_name() const
Returns a unique name used for debugging.
get_image_modified
Returns a sequence number which is guaranteed to change at least every time the texture image data (i...
A rectangular subregion within a window for rendering into.
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.
void draw(Thread *current_thread)
Asks all the bins to draw themselves in the correct order.
get_prepared_objects
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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 ...
int get_lens_index() const
Gets the index into a lens_node lens array.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static AsyncTaskManager * get_global_ptr()
Returns a pointer to the global AsyncTaskManager.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_gsg
Returns the GSG that is associated with this window.
has_size
Returns true if the window size has been specified, false otherwise.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.