52 #if defined(_WIN32) && defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
57 #define WINDOWS_LEAN_AND_MEAN
60 #undef WINDOWS_LEAN_AND_MEAN
69 PStatCollector GraphicsEngine::_wait_pcollector(
"Wait:Thread sync");
71 PStatCollector GraphicsEngine::_app_pcollector(
"App:Show code:General");
72 PStatCollector GraphicsEngine::_render_frame_pcollector(
"App:render_frame");
76 PStatCollector GraphicsEngine::_cull_setup_pcollector(
"Cull:Setup");
81 PStatCollector GraphicsEngine::_flip_begin_pcollector(
"Wait:Flip:Begin");
82 PStatCollector GraphicsEngine::_flip_end_pcollector(
"Wait:Flip:End");
83 PStatCollector GraphicsEngine::_transform_states_pcollector(
"TransformStates");
84 PStatCollector GraphicsEngine::_transform_states_unused_pcollector(
"TransformStates:Unused");
85 PStatCollector GraphicsEngine::_render_states_pcollector(
"RenderStates");
86 PStatCollector GraphicsEngine::_render_states_unused_pcollector(
"RenderStates:Unused");
87 PStatCollector GraphicsEngine::_cyclers_pcollector(
"PipelineCyclers");
88 PStatCollector GraphicsEngine::_dirty_cyclers_pcollector(
"Dirty PipelineCyclers");
92 PStatCollector GraphicsEngine::_sw_sprites_pcollector(
"SW Sprites");
93 PStatCollector GraphicsEngine::_vertex_data_small_pcollector(
"Vertex Data:Small");
94 PStatCollector GraphicsEngine::_vertex_data_independent_pcollector(
"Vertex Data:Independent");
95 PStatCollector GraphicsEngine::_vertex_data_pending_pcollector(
"Vertex Data:Pending");
96 PStatCollector GraphicsEngine::_vertex_data_resident_pcollector(
"Vertex Data:Resident");
97 PStatCollector GraphicsEngine::_vertex_data_compressed_pcollector(
"Vertex Data:Compressed");
98 PStatCollector GraphicsEngine::_vertex_data_unused_disk_pcollector(
"Vertex Data:Disk:Unused");
99 PStatCollector GraphicsEngine::_vertex_data_used_disk_pcollector(
"Vertex Data:Disk:Used");
103 PStatCollector GraphicsEngine::_cnode_volume_pcollector(
"Collision Volumes:CollisionNode");
104 PStatCollector GraphicsEngine::_gnode_volume_pcollector(
"Collision Volumes:GeomNode");
105 PStatCollector GraphicsEngine::_geom_volume_pcollector(
"Collision Volumes:Geom");
106 PStatCollector GraphicsEngine::_node_volume_pcollector(
"Collision Volumes:PandaNode");
107 PStatCollector GraphicsEngine::_volume_pcollector(
"Collision Volumes:CollisionSolid");
108 PStatCollector GraphicsEngine::_test_pcollector(
"Collision Tests:CollisionSolid");
109 PStatCollector GraphicsEngine::_volume_polygon_pcollector(
"Collision Volumes:CollisionPolygon");
110 PStatCollector GraphicsEngine::_test_polygon_pcollector(
"Collision Tests:CollisionPolygon");
111 PStatCollector GraphicsEngine::_volume_plane_pcollector(
"Collision Volumes:CollisionPlane");
112 PStatCollector GraphicsEngine::_test_plane_pcollector(
"Collision Tests:CollisionPlane");
113 PStatCollector GraphicsEngine::_volume_sphere_pcollector(
"Collision Volumes:CollisionSphere");
114 PStatCollector GraphicsEngine::_test_sphere_pcollector(
"Collision Tests:CollisionSphere");
115 PStatCollector GraphicsEngine::_volume_box_pcollector(
"Collision Volumes:CollisionBox");
116 PStatCollector GraphicsEngine::_test_box_pcollector(
"Collision Tests:CollisionBox");
117 PStatCollector GraphicsEngine::_volume_capsule_pcollector(
"Collision Volumes:CollisionCapsule");
118 PStatCollector GraphicsEngine::_test_capsule_pcollector(
"Collision Tests:CollisionCapsule");
119 PStatCollector GraphicsEngine::_volume_inv_sphere_pcollector(
"Collision Volumes:CollisionInvSphere");
120 PStatCollector GraphicsEngine::_test_inv_sphere_pcollector(
"Collision Tests:CollisionInvSphere");
121 PStatCollector GraphicsEngine::_volume_geom_pcollector(
"Collision Volumes:CollisionGeom");
122 PStatCollector GraphicsEngine::_test_geom_pcollector(
"Collision Tests:CollisionGeom");
123 PStatCollector GraphicsEngine::_occlusion_untested_pcollector(
"Occlusion results:Not tested");
124 PStatCollector GraphicsEngine::_occlusion_passed_pcollector(
"Occlusion results:Visible");
125 PStatCollector GraphicsEngine::_occlusion_failed_pcollector(
"Occlusion results:Occluded");
126 PStatCollector GraphicsEngine::_occlusion_tests_pcollector(
"Occlusion tests");
135 INLINE
static bool operator < (
const CullKey &a,
const CullKey &b) {
136 if (a._gsg != b._gsg) {
137 return a._gsg < b._gsg;
139 if (a._camera != b._camera) {
140 return a._camera < b._camera;
142 return a._lens_index < b._lens_index;
154 _lock(
"GraphicsEngine::_lock"),
155 _loaded_textures_lock(
"GraphicsEngine::_loaded_textures_lock")
157 if (_pipeline ==
nullptr) {
161 _windows_sorted =
true;
162 _window_sort_index = 0;
167 <<
"Using threading model " << _threading_model <<
"\n";
169 _auto_flip = auto_flip;
170 _portal_enabled =
false;
171 _flip_state = FS_flip;
173 _singular_warning_last_frame =
false;
174 _singular_warning_this_frame =
false;
184 if (_app_pcollector.is_started()) {
185 _app_pcollector.stop();
200 if (!threading_model.is_single_threaded()) {
201 display_cat.warning()
202 <<
"Threading model " << threading_model
203 <<
" requested but threading is not available. Ignoring.\n";
208 #ifndef THREADED_PIPELINE
209 if (!threading_model.is_single_threaded()) {
210 display_cat.warning()
211 <<
"Threading model " << threading_model
212 <<
" requested but multithreaded render pipelines not enabled in build.\n";
213 if (!allow_nonpipeline_threads) {
214 display_cat.warning()
215 <<
"Ignoring requested threading model.\n";
218 display_cat.warning()
219 <<
"Danger! Creating requested render threads anyway!\n";
223 _threading_model = threading_model;
235 result = _threading_model;
258 const string &name,
int sort,
290 int x_size = 0, y_size = 0;
295 if ((x_size == 0)&&(y_size == 0)) {
296 flags |= GraphicsPipe::BF_size_track_host;
298 if (host !=
nullptr) {
306 if (host ==
nullptr) {
307 if (gsg !=
nullptr) {
316 if ((host->
get_gsg()==
nullptr)||
318 (!host->
get_gsg()->is_valid())||
319 (host->
get_gsg()->needs_reset())) {
322 if ((host->
get_gsg()==
nullptr)||
324 (!host->
get_gsg()->is_valid())||
325 (host->
get_gsg()->needs_reset())) {
335 nassertr(pipe !=
nullptr,
nullptr);
336 if (gsg !=
nullptr) {
337 nassertr(pipe == gsg->
get_pipe(),
nullptr);
342 if ((flags & GraphicsPipe::BF_require_callback_window)!=0) {
344 if (this_gsg ==
nullptr) {
347 this_gsg = pipe->make_callback_gsg(
this);
349 if (this_gsg !=
nullptr) {
351 window->_sort = sort;
352 do_add_window(window);
353 do_add_gsg(window->
get_gsg(), pipe);
354 display_cat.info() <<
"Created output of type CallbackGraphicsWindow\n";
365 bool can_use_parasite =
false;
366 if ((host !=
nullptr)&&
367 ((flags&GraphicsPipe::BF_require_window)==0)&&
368 ((flags&GraphicsPipe::BF_require_callback_window)==0)&&
369 ((flags&GraphicsPipe::BF_refuse_parasite)==0)&&
370 ((flags&GraphicsPipe::BF_can_bind_color)==0)&&
371 ((flags&GraphicsPipe::BF_can_bind_every)==0)&&
372 ((flags&GraphicsPipe::BF_rtt_cumulative)==0)&&
373 ((flags&GraphicsPipe::BF_can_bind_layered)==0)) {
374 if ((flags&GraphicsPipe::BF_fb_props_optional) ||
376 can_use_parasite =
true;
385 if ((prefer_parasite_buffer) &&
386 (can_use_parasite) &&
387 (x_size <= host->get_x_size())&&
388 (y_size <= host->get_y_size())&&
391 buffer->_sort = sort;
392 do_add_window(buffer);
393 do_add_gsg(host->
get_gsg(), pipe);
394 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
401 if (force_parasite_buffer && can_use_parasite) {
403 buffer->_sort = sort;
404 do_add_window(buffer);
405 do_add_gsg(host->
get_gsg(), pipe);
406 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
412 for (
int retry=0; retry<10; retry++) {
413 bool precertify =
false;
415 pipe->make_output(name, fb_prop, win_prop, flags,
this, gsg, host, retry, precertify);
416 if (window !=
nullptr) {
417 window->_sort = sort;
418 if (precertify && gsg !=
nullptr && window->
get_gsg() == gsg) {
419 do_add_window(window);
421 <<
"Created output of type " << window->get_type() <<
"\n";
424 do_add_window(window);
426 if (window->is_valid()) {
428 <<
"Created output of type " << window->get_type() <<
"\n";
430 if (window->get_fb_properties().subsumes(fb_prop)) {
433 if (flags & GraphicsPipe::BF_fb_props_optional) {
434 display_cat.warning()
435 <<
"FrameBufferProperties available less than requested.\n";
436 display_cat.warning(
false)
437 <<
" requested: " << fb_prop <<
"\n"
438 <<
" got: " << window->get_fb_properties() <<
"\n";
442 <<
"Could not get requested FrameBufferProperties; abandoning window.\n";
443 display_cat.error(
false)
444 <<
" requested: " << fb_prop <<
"\n"
445 <<
" got: " << window->get_fb_properties() <<
"\n";
449 << window->get_type() <<
" wouldn't open; abandoning.\n";
450 display_cat.debug(
false)
451 <<
" requested: " << fb_prop <<
"\n";
462 if (can_use_parasite) {
464 buffer->_sort = sort;
465 do_add_window(buffer);
466 do_add_gsg(host->
get_gsg(), pipe);
467 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
490 nassertr(window !=
nullptr,
false);
491 nassertr(
this == window->
get_engine(),
false);
493 window->_sort = sort;
494 do_add_window(window);
497 <<
"Added output of type " << window->get_type() <<
"\n";
521 nassertr(window !=
nullptr,
false);
529 if (!_windows_sorted) {
532 count = _windows.erase(ptwin);
537 MutexHolder new_windows_holder(_new_windows_lock, current_thread);
538 size_t old_size = _new_windows.size();
539 _new_windows.erase(std::remove(_new_windows.begin(), _new_windows.end(), ptwin), _new_windows.end());
540 if (count == 0 && _new_windows.size() < old_size) {
550 do_remove_window(window, current_thread);
553 if (gsg !=
nullptr) {
555 if (pgo !=
nullptr) {
557 bool any_common =
false;
560 Windows::iterator wi;
561 for (wi = _windows.
begin(); wi != _windows.
end() && !any_common; ++wi) {
563 if (gsg2 !=
nullptr &&
580 nassertr(count == 1,
true);
599 old_windows.
swap(_windows);
601 nassertv(win !=
nullptr);
602 do_remove_window(win, current_thread);
604 if (gsg !=
nullptr) {
610 MutexHolder new_windows_holder(_new_windows_lock, current_thread);
612 nassertv(win !=
nullptr);
613 do_remove_window(win, current_thread);
615 if (gsg !=
nullptr) {
619 _new_windows.clear();
622 _app.do_close(
this, current_thread);
623 _app.do_pending(
this, current_thread);
624 terminate_threads(current_thread);
641 PStatClient::get_global_pstats()->
disconnect();
644 #if defined(_WIN32) && defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
647 WinInputDeviceManager::stop_thread();
661 Windows::iterator wi;
662 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
675 return _windows.
empty();
683 return _windows.
size();
691 nassertr(n >= 0 && n < (
int)_windows.
size(),
nullptr);
693 if (!_windows_sorted) {
715 _render_frame_pcollector.start();
716 if (_app_pcollector.is_started()) {
717 _app_pcollector.stop();
730 if (display_cat.is_spam()) {
732 <<
"render_frame() - frame " << global_clock->
get_frame_count() <<
"\n";
738 if (!_windows_sorted) {
742 if (sync_flip && _flip_state != FS_flip) {
743 do_flip_frame(current_thread);
749 Windows::iterator wi;
750 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
752 nassertv(win !=
nullptr);
754 do_remove_window(win, current_thread);
764 int num_drs = win->get_num_active_display_regions();
765 for (
int i = 0; i < num_drs; ++i) {
773 scene = camera_np.
get_top(current_thread);
776 scene.get_bounds(current_thread);
783 _windows.
swap(new_windows);
789 LoadedTextures::iterator lti;
790 for (lti = _loaded_textures.begin(); lti != _loaded_textures.end(); ++lti) {
791 LoadedTexture < = (*lti);
792 if (lt._tex->get_image_modified() == lt._image_modified) {
793 lt._tex->texture_uploaded();
796 _loaded_textures.clear();
801 _app.do_frame(
this, current_thread);
806 PStatTimer timer(_wait_pcollector, current_thread);
807 Threads::const_iterator ti;
808 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
809 RenderThread *thread = (*ti).second;
810 thread->_cv_mutex.acquire();
812 while (thread->_thread_state != TS_wait) {
813 thread->_cv_done.wait();
818 #if defined(THREADED_PIPELINE) && defined(DO_PSTATS)
819 _cyclers_pcollector.set_level(_pipeline->get_num_cyclers());
820 _dirty_cyclers_pcollector.set_level(_pipeline->get_num_dirty_cyclers());
824 _pipeline->iterate_all_cycler_types(pstats_count_cycler_type,
this);
825 _pipeline->iterate_dirty_cycler_types(pstats_count_dirty_cycler_type,
this);
834 TransformState::flush_level();
838 #ifdef THREADED_PIPELINE
840 PStatTimer timer(_cycle_pcollector, current_thread);
845 global_clock->
tick(current_thread);
847 throw_event(
"clock_error");
851 PStatClient::main_tick();
854 CullTraverser::_nodes_pcollector.clear_level();
855 CullTraverser::_geom_nodes_pcollector.clear_level();
856 CullTraverser::_geoms_pcollector.clear_level();
857 GeomCacheManager::_geom_cache_active_pcollector.clear_level();
858 GeomCacheManager::_geom_cache_record_pcollector.clear_level();
859 GeomCacheManager::_geom_cache_erase_pcollector.clear_level();
860 GeomCacheManager::_geom_cache_evict_pcollector.clear_level();
862 GraphicsStateGuardian::init_frame_pstats();
864 _transform_states_pcollector.set_level(TransformState::get_num_states());
866 if (pstats_unused_states) {
867 _transform_states_unused_pcollector.set_level(TransformState::get_num_unused_states());
871 _sw_sprites_pcollector.clear_level();
873 _cnode_volume_pcollector.clear_level();
874 _gnode_volume_pcollector.clear_level();
875 _geom_volume_pcollector.clear_level();
876 _node_volume_pcollector.clear_level();
877 _volume_pcollector.clear_level();
878 _test_pcollector.clear_level();
879 _volume_polygon_pcollector.clear_level();
880 _test_polygon_pcollector.clear_level();
881 _volume_plane_pcollector.clear_level();
882 _test_plane_pcollector.clear_level();
883 _volume_sphere_pcollector.clear_level();
884 _test_sphere_pcollector.clear_level();
885 _volume_box_pcollector.clear_level();
886 _test_box_pcollector.clear_level();
887 _volume_capsule_pcollector.clear_level();
888 _test_capsule_pcollector.clear_level();
889 _volume_inv_sphere_pcollector.clear_level();
890 _test_inv_sphere_pcollector.clear_level();
891 _volume_geom_pcollector.clear_level();
892 _test_geom_pcollector.clear_level();
893 _occlusion_untested_pcollector.clear_level();
894 _occlusion_passed_pcollector.clear_level();
895 _occlusion_failed_pcollector.clear_level();
896 _occlusion_tests_pcollector.clear_level();
909 _vertex_data_small_pcollector.set_level(small_buf);
910 _vertex_data_independent_pcollector.set_level(independent);
911 _vertex_data_pending_pcollector.set_level(pending);
912 _vertex_data_resident_pcollector.set_level(resident);
913 _vertex_data_compressed_pcollector.set_level(compressed);
914 _vertex_data_unused_disk_pcollector.set_level(total_disk - used_disk);
915 _vertex_data_used_disk_pcollector.set_level(used_disk);
923 Threads::const_iterator ti;
924 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
925 RenderThread *thread = (*ti).second;
926 if (thread->_thread_state == TS_wait) {
927 thread->_thread_state = TS_do_frame;
928 thread->_cv_start.notify();
930 thread->_cv_mutex.release();
935 _flip_state = _auto_flip ? FS_flip : FS_draw;
940 if (yield_timeslice) {
943 PStatTimer timer(_yield_pcollector, current_thread);
946 PStatTimer timer(_yield_pcollector, current_thread);
952 _app_pcollector.start();
953 _render_frame_pcollector.stop();
972 MutexHolder new_windows_holder(_new_windows_lock, current_thread);
973 if (_new_windows.empty()) {
977 for (
auto it = _new_windows.begin(); it != _new_windows.end(); ++it) {
980 WindowRenderer *cull =
983 WindowRenderer *draw =
988 cull->add_window(cull->_cull, window);
989 draw->add_window(draw->_draw, window);
991 cull->add_window(cull->_cdraw, window);
1003 switch (window->
get_pipe()->get_preferred_window_thread()) {
1004 case GraphicsPipe::PWT_app:
1005 _app.add_window(_app._window, window);
1008 case GraphicsPipe::PWT_draw:
1009 draw->add_window(draw->_window, window);
1017 new_windows.swap(_new_windows);
1020 do_resort_windows();
1023 for (
int i = 0; i < 2; ++i) {
1024 _app.do_windows(
this, current_thread);
1025 _app.do_pending(
this, current_thread);
1027 PStatTimer timer(_wait_pcollector, current_thread);
1028 Threads::const_iterator ti;
1029 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1030 RenderThread *thread = (*ti).second;
1031 thread->_cv_mutex.acquire();
1033 while (thread->_thread_state != TS_wait) {
1034 thread->_cv_done.wait();
1037 thread->_thread_state = TS_do_windows;
1038 thread->_cv_start.notify();
1039 thread->_cv_mutex.release();
1044 for (
auto it = new_windows.begin(); it != new_windows.end(); ++it) {
1065 if (_flip_state == FS_draw) {
1066 do_sync_frame(current_thread);
1086 if (_flip_state == FS_draw) {
1087 do_ready_flip(current_thread);
1101 if (_flip_state != FS_flip) {
1102 do_flip_frame(current_thread);
1132 if (draw_name.empty()) {
1139 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1140 RenderThread *thread = (RenderThread *)wr;
1143 while (thread->_thread_state != TS_wait) {
1144 thread->_cv_done.wait();
1149 int draw_pipeline_stage = thread->get_pipeline_stage();
1150 thread->set_pipeline_stage(pipeline_stage);
1154 thread->_texture = tex;
1155 thread->_thread_state = TS_do_extract;
1156 thread->_cv_start.notify();
1157 thread->_cv_mutex.release();
1158 thread->_cv_mutex.acquire();
1161 while (thread->_thread_state != TS_wait) {
1162 thread->_cv_done.wait();
1165 thread->set_pipeline_stage(draw_pipeline_stage);
1166 thread->_gsg =
nullptr;
1167 thread->_texture =
nullptr;
1168 return thread->_result;
1187 const Shader *shader = sattr->get_shader();
1188 nassertv(shader !=
nullptr);
1189 nassertv(gsg !=
nullptr);
1193 CPT(
RenderState) state = RenderState::make(sattr);
1196 if (draw_name.empty()) {
1201 gsg->pop_group_marker();
1206 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1207 RenderThread *thread = (RenderThread *)wr;
1210 while (thread->_thread_state != TS_wait) {
1211 thread->_cv_done.wait();
1216 int draw_pipeline_stage = thread->get_pipeline_stage();
1217 thread->set_pipeline_stage(pipeline_stage);
1221 thread->_state = state.p();
1222 thread->_work_groups = work_groups;
1223 thread->_thread_state = TS_do_compute;
1224 thread->_cv_start.notify();
1225 thread->_cv_mutex.release();
1226 thread->_cv_mutex.acquire();
1229 while (thread->_thread_state != TS_wait) {
1230 thread->_cv_done.wait();
1233 thread->set_pipeline_stage(draw_pipeline_stage);
1234 thread->_gsg =
nullptr;
1235 thread->_state =
nullptr;
1244 if (_global_ptr ==
nullptr) {
1265 _loaded_textures.push_back(LoadedTexture());
1266 LoadedTexture < = _loaded_textures.back();
1283 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1284 RenderThread *thread = (RenderThread *)wr;
1287 while (thread->_thread_state != TS_wait) {
1288 thread->_cv_done.wait();
1292 thread->_region = region;
1293 thread->_thread_state = TS_do_screenshot;
1294 thread->_cv_start.notify();
1295 thread->_cv_mutex.release();
1296 thread->_cv_mutex.acquire();
1299 while (thread->_thread_state != TS_wait) {
1300 thread->_cv_done.wait();
1303 PT(
Texture) tex = std::move(thread->_texture);
1304 thread->_region =
nullptr;
1305 thread->_texture =
nullptr;
1323 if (view_frustum_cull) {
1331 if (bv !=
nullptr && !bv->is_infinite() &&
1332 bv->as_geometric_bounding_volume() !=
nullptr) {
1335 local_frustum = bv->make_copy()->as_geometric_bounding_volume();
1336 nassertv(!local_frustum.is_null());
1341 local_frustum->xform(cull_center_transform->get_mat());
1356 bool GraphicsEngine::
1357 scene_root_func(
const PandaNode *node) {
1358 return _global_ptr->is_scene_root(node);
1365 bool GraphicsEngine::
1369 Windows::const_iterator wi;
1370 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
1373 int num_display_regions = win->get_num_active_display_regions();
1374 for (
int i = 0; i < num_display_regions; i++) {
1376 if (dr !=
nullptr) {
1383 DCAST_INTO_R(camera_node, camera.
node(),
false);
1393 scene_root = camera.
get_top(current_thread);
1396 if (scene_root.
node() == node) {
1413 void GraphicsEngine::
1416 window->_sort = sort;
1417 _windows_sorted =
false;
1426 void GraphicsEngine::
1428 Thread *current_thread) {
1429 PStatTimer timer(_cull_pcollector, current_thread);
1431 size_t wlist_size = wlist.
size();
1432 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1437 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1441 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1446 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1450 gsg->push_group_marker(
"Clear");
1451 win->
clear(current_thread);
1452 gsg->pop_group_marker();
1455 int num_display_regions = win->get_num_active_display_regions();
1456 for (
int i = 0; i < num_display_regions; i++) {
1458 if (dr !=
nullptr) {
1459 cull_and_draw_together(win, dr, current_thread);
1462 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1467 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1471 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1484 void GraphicsEngine::
1486 Thread *current_thread) {
1488 nassertv(gsg !=
nullptr);
1499 if (dr_reader.is_any_clear_active()) {
1504 scene_setup = setup_scene(gsg, &dr_reader);
1507 if (scene_setup ==
nullptr) {
1513 }
else if (!gsg->
set_scene(scene_setup)) {
1516 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
1522 if (cbobj !=
nullptr) {
1531 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1538 gsg->pop_group_marker();
1546 void GraphicsEngine::
1548 PStatTimer timer(_cull_pcollector, current_thread);
1550 _singular_warning_last_frame = _singular_warning_this_frame;
1551 _singular_warning_this_frame =
false;
1556 AlreadyCulled already_culled;
1558 size_t wlist_size = wlist.
size();
1559 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1564 int num_display_regions = win->get_num_active_display_regions();
1565 for (
int i = 0; i < num_display_regions; ++i) {
1567 if (dr !=
nullptr) {
1572 PStatTimer timer(_cull_setup_pcollector, current_thread);
1574 scene_setup = setup_scene(gsg, &dr_reader);
1575 if (scene_setup ==
nullptr) {
1580 key._camera = dr_reader.get_camera();
1581 key._lens_index = dr_reader.get_lens_index();
1584 AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(std::move(key),
nullptr)).first;
1585 if ((*aci).second ==
nullptr) {
1589 if (cull_result !=
nullptr) {
1590 cull_result = cull_result->make_next();
1596 cull_to_bins(win, gsg, dr, scene_setup, cull_result, current_thread);
1610 dr->
set_cull_result(std::move(cull_result), MOVE(scene_setup), current_thread);
1620 void GraphicsEngine::
1627 if (cbobj !=
nullptr) {
1636 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1639 PStatTimer timer(_cull_sort_pcollector, current_thread);
1640 cull_result->
finish_cull(scene_setup, current_thread);
1648 void GraphicsEngine::
1652 size_t wlist_size = wlist.
size();
1653 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1664 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1668 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1673 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1680 win->
get_gsg()->push_group_marker(
"Clear");
1681 win->
clear(current_thread);
1682 win->
get_gsg()->pop_group_marker();
1685 if (display_cat.is_spam()) {
1687 <<
"Drawing window " << win->
get_name() <<
"\n";
1689 int num_display_regions = win->get_num_active_display_regions();
1690 for (
int i = 0; i < num_display_regions; ++i) {
1692 if (dr !=
nullptr) {
1693 do_draw(win, gsg, dr, current_thread);
1697 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1703 gsg->issue_timer_query(GraphicsStateGuardian::_command_latency_pcollector.get_index());
1711 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1715 PStatGPUTimer timer(gsg, GraphicsEngine::_flip_end_pcollector, current_thread);
1722 if (display_cat.is_spam()) {
1724 <<
"Not drawing window " << win->
get_name() <<
"\n";
1729 if (display_cat.is_spam()) {
1731 <<
"Window " << win->
get_name() <<
" is inactive\n";
1741 void GraphicsEngine::
1743 Windows::const_iterator wi;
1744 for (wi = wlist.
begin(); wi != wlist.
end(); ++wi) {
1746 if (win->
begin_frame(GraphicsOutput::FM_refresh, current_thread)) {
1747 win->
end_frame(GraphicsOutput::FM_refresh, current_thread);
1757 void GraphicsEngine::
1762 for (
size_t i = 0; i < wlist.
size(); ++i) {
1763 wlist[i]->process_events();
1772 void GraphicsEngine::
1774 size_t num_windows = wlist.
size();
1776 size_t warray_count = 0;
1780 for (i = 0; i < num_windows; ++i) {
1783 nassertv(warray_count < num_windows);
1784 warray[warray_count] = win;
1787 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1792 for (i = 0; i < warray_count; ++i) {
1794 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1804 void GraphicsEngine::
1806 Windows::const_iterator wi;
1807 for (wi = wlist.
begin(); wi != wlist.
end(); ++wi) {
1810 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1820 void GraphicsEngine::
1821 do_sync_frame(
Thread *current_thread) {
1825 PStatTimer timer(_sync_pcollector, current_thread);
1827 nassertv(_flip_state == FS_draw);
1831 Threads::const_iterator ti;
1832 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1833 RenderThread *thread = (*ti).second;
1834 thread->_cv_mutex.acquire();
1835 thread->_cv_mutex.release();
1838 _flip_state = FS_sync;
1845 void GraphicsEngine::
1846 do_ready_flip(
Thread *current_thread) {
1850 PStatTimer timer(_sync_pcollector, current_thread);
1852 nassertv(_flip_state == FS_draw);
1856 Threads::const_iterator ti;
1857 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1858 RenderThread *thread = (*ti).second;
1859 thread->_cv_mutex.acquire();
1860 thread->_cv_mutex.release();
1862 _app.do_ready_flip(
this,current_thread);
1863 _flip_state = FS_sync;
1870 void GraphicsEngine::
1871 do_flip_frame(
Thread *current_thread) {
1875 PStatTimer timer(_flip_pcollector, current_thread);
1877 nassertv(_flip_state == FS_draw || _flip_state == FS_sync);
1883 PStatTimer timer(_wait_pcollector, current_thread);
1884 Threads::const_iterator ti;
1885 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1886 RenderThread *thread = (*ti).second;
1887 thread->_cv_mutex.acquire();
1889 while (thread->_thread_state != TS_wait) {
1890 thread->_cv_done.wait();
1896 _app.do_flip(
this, current_thread);
1899 Threads::const_iterator ti;
1900 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1901 RenderThread *thread = (*ti).second;
1902 nassertv(thread->_thread_state == TS_wait);
1903 thread->_thread_state = TS_do_flip;
1904 thread->_cv_start.notify();
1905 thread->_cv_mutex.release();
1909 _flip_state = FS_flip;
1919 Thread *current_thread = dr->get_current_thread();
1920 PStatTimer timer(_cull_setup_pcollector, current_thread);
1925 nassertr(window !=
nullptr,
nullptr);
1934 DCAST_INTO_R(camera_node, camera.
node(),
nullptr);
1954 scene_root = camera.
get_top(current_thread);
1970 if (camera_transform->is_invalid()) {
1972 if (!_singular_warning_last_frame) {
1973 display_cat.warning()
1974 <<
"Scene " << scene_root <<
" has net scale ("
1976 _singular_warning_this_frame =
true;
1981 if (world_transform->is_invalid()) {
1983 if (!_singular_warning_last_frame) {
1984 display_cat.warning()
1985 <<
"Camera " << camera <<
" has net scale ("
1988 _singular_warning_this_frame =
true;
1992 CPT(
RenderState) initial_state = camera_node->get_initial_state();
2002 initial_state = initial_state->compose(get_invert_polygon_state());
2011 scene_setup->set_initial_state(initial_state);
2018 CPT(
TransformState) cs_world_transform = cs_transform->compose(world_transform);
2027 void GraphicsEngine::
2038 cull_result = cdata->_cull_result;
2039 scene_setup = cdata->_scene_setup;
2048 if (dr_reader.is_any_clear_active()) {
2050 gsg->
clear(dr_reader.get_object());
2053 cbobj = dr_reader.get_draw_callback();
2056 if (cbobj !=
nullptr) {
2061 static CPT(
RenderState) state = RenderState::make(
2062 DepthTestAttrib::make(DepthTestAttrib::M_none));
2072 }
else if (cull_result ==
nullptr || scene_setup ==
nullptr) {
2082 }
else if (!gsg->
set_scene(scene_setup)) {
2085 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
2089 cull_result->
draw(current_thread);
2094 gsg->pop_group_marker();
2102 void GraphicsEngine::
2104 nassertv(window !=
nullptr);
2111 window->_internal_sort_index = _window_sort_index;
2112 ++_window_sort_index;
2114 if (display_cat.is_debug()) {
2116 <<
"Created " << window->get_type() <<
" " << (
void *)window <<
"\n";
2120 _new_windows.push_back(window);
2128 void GraphicsEngine::
2130 nassertv(gsg !=
nullptr);
2134 gsg->_threading_model = _threading_model;
2135 if (!_default_loader.is_null()) {
2139 auto_adjust_capabilities(gsg);
2141 WindowRenderer *draw =
2153 void GraphicsEngine::
2155 nassertv(window !=
nullptr);
2159 if (!_windows_sorted) {
2160 do_resort_windows();
2164 _app.remove_window(window);
2165 Threads::const_iterator ti;
2166 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2167 RenderThread *thread = (*ti).second;
2168 thread->remove_window(window);
2173 _app.do_pending(
this, current_thread);
2175 if (display_cat.is_debug()) {
2177 <<
"Removed " << window->get_type() <<
" " << (
void *)window <<
"\n";
2185 void GraphicsEngine::
2186 do_resort_windows() {
2187 _windows_sorted =
true;
2189 _app.resort_windows();
2190 Threads::const_iterator ti;
2191 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2192 RenderThread *thread = (*ti).second;
2193 thread->resort_windows();
2219 void GraphicsEngine::
2241 if (textures_auto_power_2 && (textures_power_2 == ATS_none)) {
2243 <<
"Invalid panda config file: if you set the config-variable\n"
2244 <<
"textures_auto_power_2 to true, you must set the config-variable"
2245 <<
"textures_power_2 to 'up' or 'down'.\n";
2246 textures_power_2 = ATS_down;
2263 <<
"The 'textures_power_2' configuration is set to 'none', meaning \n"
2264 <<
"that non-power-of-two texture support is required, but the video \n"
2265 <<
"driver I'm trying to use does not support non-power-of-two textures.\n";
2267 if (textures_power_2 != ATS_none) {
2269 <<
"The 'none' did not come from the config file. In other words,\n"
2270 <<
"the variable 'textures_power_2' was altered procedurally.\n";
2272 if (textures_auto_power_2) {
2274 <<
"It is possible that it was set by panda's automatic mechanisms,\n"
2275 <<
"which are currently enabled, because 'textures_auto_power_2' is\n"
2276 <<
"true. Panda's automatic mechanisms assume that if one\n"
2277 <<
"window supports non-power-of-two textures, then they all will.\n"
2278 <<
"This assumption works for most games, but not all.\n"
2279 <<
"In particular, it can fail if the game creates multiple windows\n"
2280 <<
"on multiple displays with different video cards.\n";
2289 void GraphicsEngine::
2290 terminate_threads(
Thread *current_thread) {
2295 PStatTimer timer(_wait_pcollector, current_thread);
2299 Threads::const_iterator ti;
2300 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2301 RenderThread *thread = (*ti).second;
2302 thread->_cv_mutex.acquire();
2306 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2307 RenderThread *thread = (*ti).second;
2308 thread->_thread_state = TS_terminate;
2309 thread->_cv_start.notify();
2310 thread->_cv_mutex.release();
2314 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2315 RenderThread *thread = (*ti).second;
2328 void GraphicsEngine::
2329 pstats_count_cycler_type(
TypeHandle type,
int count,
void *data) {
2331 CyclerTypeCounters::iterator ci =
self->_all_cycler_types.find(type);
2332 if (ci == self->_all_cycler_types.end()) {
2334 ci =
self->_all_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2336 (*ci).second.set_level(count);
2345 void GraphicsEngine::
2346 pstats_count_dirty_cycler_type(
TypeHandle type,
int count,
void *data) {
2348 CyclerTypeCounters::iterator ci =
self->_dirty_cycler_types.find(type);
2349 if (ci == self->_dirty_cycler_types.end()) {
2351 ci =
self->_dirty_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2353 (*ci).second.set_level(count);
2363 get_invert_polygon_state() {
2367 if (state ==
nullptr) {
2368 state = RenderState::make(CullFaceAttrib::make_reverse());
2382 GraphicsEngine::WindowRenderer *GraphicsEngine::
2383 get_window_renderer(
const string &name,
int pipeline_stage) {
2390 Threads::iterator ti = _threads.find(name);
2391 if (ti != _threads.end()) {
2392 return (*ti).second.p();
2395 PT(RenderThread) thread =
new RenderThread(name,
this);
2396 thread->set_min_pipeline_stage(pipeline_stage);
2399 bool started = thread->start(TP_normal,
true);
2400 nassertr(started, thread.p());
2401 _threads[name] = thread;
2403 nassertr(thread->get_pipeline_stage() < _pipeline->
get_num_stages(), thread.p());
2411 GraphicsEngine::WindowRenderer::
2412 WindowRenderer(
const string &name) :
2413 _wl_lock(string(
"GraphicsEngine::WindowRenderer::_wl_lock ") + name)
2420 void GraphicsEngine::WindowRenderer::
2430 void GraphicsEngine::WindowRenderer::
2433 wlist.insert(window);
2441 void GraphicsEngine::WindowRenderer::
2443 nassertv(window !=
nullptr);
2448 _cdraw.erase(ptwin);
2451 Windows::iterator wi;
2453 wi = _window.find(ptwin);
2454 if (wi != _window.end()) {
2464 if (ptwin->is_valid()) {
2465 _pending_close.push_back(ptwin);
2475 void GraphicsEngine::WindowRenderer::
2484 if (display_cat.is_debug()) {
2486 <<
"Windows resorted:";
2487 Windows::const_iterator wi;
2488 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2490 display_cat.debug(
false)
2493 display_cat.debug(
false)
2496 for (wi = _draw.begin(); wi != _draw.end(); ++wi) {
2498 display_cat.debug(
false)
2501 display_cat.debug(
false)
2511 void GraphicsEngine::WindowRenderer::
2513 PStatTimer timer(engine->_do_frame_pcollector, current_thread);
2516 engine->cull_to_bins(_cull, current_thread);
2517 engine->cull_and_draw_together(_cdraw, current_thread);
2518 engine->draw_bins(_draw, current_thread);
2519 engine->process_events(_window, current_thread);
2523 if (any_done_gsgs()) {
2526 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2531 engine->close_gsg(pipe, gsg);
2534 new_gsgs.insert(gsg);
2538 _gsgs.swap(new_gsgs);
2548 void GraphicsEngine::WindowRenderer::
2552 engine->process_events(_window, current_thread);
2554 engine->make_contexts(_cdraw, current_thread);
2555 engine->make_contexts(_draw, current_thread);
2561 void GraphicsEngine::WindowRenderer::
2564 engine->flip_windows(_cdraw, current_thread);
2565 engine->flip_windows(_draw, current_thread);
2571 void GraphicsEngine::WindowRenderer::
2574 engine->ready_flip_windows(_cdraw, current_thread);
2575 engine->ready_flip_windows(_draw, current_thread);
2582 void GraphicsEngine::WindowRenderer::
2585 Windows::iterator wi;
2586 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2594 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2599 engine->close_gsg(pipe, gsg);
2602 new_gsgs.insert(gsg);
2606 _gsgs.swap(new_gsgs);
2613 void GraphicsEngine::WindowRenderer::
2617 if (!_pending_close.empty()) {
2618 if (display_cat.is_debug()) {
2620 <<
"_pending_close.size() = " << _pending_close.size() <<
"\n";
2626 Windows::iterator wi;
2627 Windows pending_close;
2628 _pending_close.swap(pending_close);
2629 for (wi = pending_close.begin(); wi != pending_close.end(); ++wi) {
2641 bool GraphicsEngine::WindowRenderer::
2642 any_done_gsgs()
const {
2643 GSGs::const_iterator gi;
2644 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2645 if ((*gi)->get_ref_count() == 1) {
2656 GraphicsEngine::RenderThread::
2659 WindowRenderer(name),
2661 _cv_mutex(string(
"GraphicsEngine::RenderThread ") + name),
2662 _cv_start(_cv_mutex),
2665 _thread_state = TS_wait;
2672 void GraphicsEngine::RenderThread::
2678 nassertv(_cv_mutex.debug_is_locked());
2680 switch (_thread_state) {
2685 do_pending(_engine, current_thread);
2686 do_frame(_engine, current_thread);
2690 do_flip(_engine, current_thread);
2694 do_pending(_engine, current_thread);
2698 do_windows(_engine, current_thread);
2699 do_pending(_engine, current_thread);
2703 nassertd(_gsg !=
nullptr && _state !=
nullptr) break;
2706 _state->get_attrib(sattr);
2707 _gsg->push_group_marker(std::string(
"Compute ") + sattr->get_shader()->get_filename(Shader::ST_compute).get_basename());
2708 _gsg->set_state_and_transform(_state, TransformState::make_identity());
2709 _gsg->dispatch_compute(_work_groups[0], _work_groups[1], _work_groups[2]);
2710 _gsg->pop_group_marker();
2715 nassertd(_gsg !=
nullptr && _texture !=
nullptr) break;
2716 _result = _gsg->extract_texture_data(_texture);
2719 case TS_do_screenshot:
2720 nassertd(_region !=
nullptr) break;
2721 _texture = _region->get_screenshot();
2725 do_pending(_engine, current_thread);
2726 do_close(_engine, current_thread);
2727 _thread_state = TS_done;
2737 _thread_state = TS_wait;
2741 PStatTimer timer(_wait_pcollector, current_thread);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void stop_threads()
Stops any threads that are currently running.
static AsyncTaskManager * get_global_ptr()
Returns a pointer to the global AsyncTaskManager.
static void consider_flush_global_index()
If there is a global BamCache object, calls consider_flush_index() on it.
static void flush_global_index()
If there is a global BamCache object, calls flush_index() on it.
This CullHandler sends all of the geoms it receives into a CullResult object, for binning (and later ...
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
This special window object doesn't represent a window in its own right, but instead hooks into some t...
This is a generic object that can be assigned to a callback at various points in the rendering proces...
virtual void do_callback(CallbackData *cbdata)
This method called when the callback is triggered; it *replaces* the original function.
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
is_active
Returns the current setting of the active flag on the camera.
get_scene
Returns the scene that will be rendered by the camera.
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...
A ClockObject keeps track of elapsed real time and discrete time.
void tick(Thread *current_thread=Thread::get_current_thread())
Instructs the clock that a new frame has just begun.
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
bool check_errors(Thread *current_thread)
Returns true if a clock error was detected since the last time check_errors() was called.
This defines the abstract interface for an object that receives Geoms identified by the CullTraverser...
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins,...
void draw(Thread *current_thread)
Asks all the bins to draw themselves in the correct order.
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...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
void set_view_frustum(GeometricBoundingVolume *view_frustum)
Specifies the bounding volume that corresponds to the view frustum.
virtual void end_traverse()
Should be called when the traverser has finished traversing its scene, this gives it a chance to do a...
virtual void set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsg, bool dr_incomplete_render)
Sets the SceneSetup object that indicates the initial camera position, etc.
void set_cull_handler(CullHandler *cull_handler)
Specifies the object that will receive the culled Geoms.
static void flush_level()
Flushes the PStatCollectors used during traversal.
void traverse(const NodePath &root)
Begins the traversal from the indicated node.
static void flush_level()
Flushes the PStatCollectors used during traversal.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This specialization on CallbackData is passed when the callback is initiated from the cull traversal,...
This specialization on CallbackData is passed when the callback is initiated from the draw traversal,...
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
GraphicsOutput * get_window() const
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
int get_lens_index() const
Gets the index into a lens_node lens array.
NodePath get_camera() const
Returns the camera associated with this DisplayRegion, or an empty NodePath if no camera is associate...
int get_pixel_width(int i=0) const
Returns the width of the DisplayRegion in pixels.
int get_pixel_height(int i=0) const
Returns the height of the DisplayRegion in pixels.
A rectangular subregion within a window for rendering into.
is_stereo
Returns true if this is a StereoDisplayRegion, false otherwise.
get_cull_traverser
Returns the CullTraverser that will be used to draw the contents of this DisplayRegion.
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.
get_incomplete_render
Returns the incomplete_render flag.
CullResult * get_cull_result(Thread *current_thread) const
Returns the CullResult value that was stored on this DisplayRegion, presumably by the last successful...
PStatCollector & get_draw_region_pcollector()
Returns a PStatCollector for timing the draw operation for just this DisplayRegion.
PStatCollector & get_cull_region_pcollector()
Returns a PStatCollector for timing the cull operation for just this DisplayRegion.
const std::string & get_debug_name() const
Returns a unique name used for debugging.
get_cull_callback
Returns the CallbackObject set by set_cull_callback().
This special kind of CullHandler immediately draws its contents as soon as it receives them.
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,...
std::string get_basename() const
Returns the basename part of the filename.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
static void flush_level()
Flushes the PStatCollectors used during traversal.
static SimpleLru * get_small_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that are deemed too...
static SimpleLru * get_independent_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that have not (yet)...
static void lru_epoch()
Marks that an epoch has passed in each LRU.
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
This class is the main interface to controlling the render process.
get_threading_model
Returns the threading model that will be applied to future objects.
get_window
Returns the nth window or buffers managed by the engine, in sorted order.
void reset_all_windows(bool swapchain)
Resets the framebuffer of the current window.
void remove_all_windows()
Removes and closes all windows from the engine.
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...
void ready_flip()
Waits for all the threads that started drawing their last frame to finish drawing.
void open_windows()
Fully opens (or closes) any windows that have recently been requested open or closed,...
void flip_frame()
Waits for all the threads that started drawing their last frame to finish drawing,...
bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg)
Asks the indicated GraphicsStateGuardian to retrieve the texture memory image of the indicated textur...
bool is_empty() const
Returns true if there are no windows or buffers managed by the engine, false if there is at least one...
bool remove_window(GraphicsOutput *window)
Removes the indicated window or offscreen buffer from the set of windows that will be processed when ...
set_threading_model
Specifies how future objects created via make_gsg(), make_buffer(), and make_output() will be threade...
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.
void render_frame()
Renders the next frame in all the registered windows, and flips all of the frame buffers.
~GraphicsEngine()
Gracefully cleans up the graphics engine and its related threads and windows.
GraphicsEngine(Pipeline *pipeline=nullptr)
Creates a new GraphicsEngine object.
void texture_uploaded(Texture *tex)
This method is called by the GraphicsStateGuardian after a texture has been successfully uploaded to ...
void sync_frame()
Waits for all the threads that started drawing their last frame to finish drawing.
get_num_windows
Returns the number of windows (or buffers) managed by the engine.
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...
static void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup, GraphicsStateGuardian *gsg, Thread *current_thread)
Fires off a cull traversal using the indicated camera.
This is a base class for the various different classes that represent the result of a frame of render...
virtual void ready_flip()
This function will be called within the draw thread after end_frame() has been called on all windows,...
get_inverted
Returns the current setting of the inverted flag.
get_pipe
Returns the GraphicsPipe that this window is associated with.
virtual void begin_flip()
This function will be called within the draw thread after end_frame() has been called on all windows,...
is_active
Returns true if the window is ready to be rendered into, false otherwise.
get_gsg
Returns the GSG that is associated with this window.
virtual void clear_pipe()
Sets the window's _pipe pointer to NULL; this is generally called only as a precursor to deleting the...
PStatCollector & get_draw_window_pcollector()
Returns a PStatCollector for timing the draw operation for just this GraphicsOutput.
PStatCollector & get_cull_window_pcollector()
Returns a PStatCollector for timing the cull operation for just this GraphicsOutput.
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.
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
bool get_delete_flag() const
Returns the current setting of the delete flag.
void change_scenes(DisplayRegionPipelineReader *new_dr)
Called by the GraphicsEngine when the window is about to change to another DisplayRegion.
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
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 void reset_window(bool swapchain)
Resets the window framebuffer from its derived children.
virtual GraphicsOutput * get_host()
This is normally called only from within make_texture_buffer().
get_engine
Returns the graphics engine that created this output.
bool is_valid() const
Returns true if the output is fully created and ready for rendering, false otherwise.
virtual void request_close()
This is called by the GraphicsEngine to request that the window (or whatever) close itself or,...
get_sort
Returns the sorting order of this particular GraphicsOutput.
get_name
Returns the name that was passed to the GraphicsOutput constructor.
PStatCollector & get_clear_window_pcollector()
Returns a PStatCollector for timing the clear operation for just this GraphicsOutput.
virtual void request_open()
This is called by the GraphicsEngine to request that the window (or whatever) open itself or,...
virtual bool flip_ready() const
Returns true if a frame has been rendered and needs to be flipped, false otherwise.
virtual void clear(Thread *current_thread)
Clears the entire framebuffer before rendering, according to the settings of get_color_clear_active()...
virtual void set_close_now()
This is called by the GraphicsEngine to insist that the output be closed immediately.
An object to create GraphicsOutputs that share a particular 3-D API.
get_gsg
Returns the nth GSG in the universe.
Encapsulates all the communication with a particular instance of a given rendering backend.
virtual void clear_before_callback()
Resets any non-standard graphics state that might give a callback apoplexy.
is_valid
Returns true if the GSG has been correctly initialized within a graphics context, false if there has ...
get_pipe
Returns the graphics pipe on which this GSG was created.
void release_all()
Releases all prepared objects.
set_scene
Sets the SceneSetup object that indicates the initial camera position, etc.
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
bool needs_reset() const
Returns true if the gsg is marked as needing a reset.
get_supports_tex_non_pow2
Returns true if this GSG can handle non power of two sized textures.
virtual void clear_state_and_transform()
Forgets the current graphics state and current transform, so that the next call to set_state_and_tran...
set_loader
Sets the Loader object that will be used by this GSG to load textures when necessary,...
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
get_prepared_objects
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
virtual bool extract_texture_data(Texture *tex)
This method should only be called by the GraphicsEngine.
virtual void end_scene()
Called between begin_frame() and end_frame() to mark the end of drawing commands for a "scene" (usual...
get_timer_queries_active
Returns true if timer queries are currently enabled on this GSG.
virtual void set_state_and_transform(const RenderState *state, const TransformState *transform)
Simultaneously resets the render state and the transform state.
virtual void clear(DrawableRegion *clearable)
Clears the framebuffer within the current DisplayRegion, according to the flags indicated by the give...
const GraphicsThreadingModel & get_threading_model() const
Returns the threading model that was used to create this GSG.
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.
virtual bool begin_scene()
Called between begin_frame() and end_frame() to mark the beginning of drawing commands for a "scene" ...
This represents the user's specification of how a particular frame is handled by the various threads.
int get_cull_stage() const
Returns the pipeline stage from which the cull thread should access data.
bool get_cull_sorting() const
Returns true if the model involves a separate cull pass, or false if culling happens implicitly,...
const std::string & get_cull_name() const
Returns the name of the thread that will handle culling in this model.
bool is_default() const
Returns true if the threading model is the default, cull-then-draw single- threaded model,...
const std::string & get_draw_name() const
Returns the name of the thread that will handle sending the actual graphics primitives to the graphic...
int get_draw_stage() const
Returns the pipeline stage from which the draw thread should access data.
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...
bool get_lens_active(int index) const
Returns the active flag for the nth lens.
A base class for any number of different kinds of lenses, linear and otherwise.
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
Similar to MutexHolder, but for a light reentrant mutex.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
LVecBase3 get_scale() const
Retrieves the scale component of the transform.
bool is_empty() const
Returns true if the NodePath contains no nodes.
PandaNode * node() const
Returns the referenced node of the path.
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...
get_parent
Returns the NodePath to the parent of the referenced node: that is, this NodePath,...
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
static void disconnect()
Closes the connection previously established.
static bool is_connected()
Returns true if the client believes it is connected to a working PStatServer, false otherwise.
A lightweight class that represents a single element that may be timed and/or counted via stats.
This is a special type of PStatTimer that also uses a timer query on the GSG to measure how long a ta...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
A basic node of the scene graph or data graph.
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...
This is a special GraphicsOutput type that acts a lot like a GraphicsBuffer, effectively allowing ren...
This class manages a staged pipeline of data, for instance the render pipeline, so that each stage of...
void cycle()
Flows all the pipeline data down to the next stage.
int get_num_stages() const
Returns the number of stages required for the pipeline.
static Pipeline * get_render_pipeline()
Returns a pointer to the global render pipeline.
void set_min_stages(int min_stages)
Ensures that at least the indicated number of stages are in the pipeline.
A table of objects that are saved within the graphics context for reference by handle later.
void release_all()
Releases all prepared objects of all kinds at once.
bool debug_is_locked() const
Returns true if the current thread has locked the ReMutex, false otherwise.
Similar to MutexHolder, but for a reentrant mutex.
get_ref_count
Returns the current reference count.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
static int get_num_states()
Returns the total number of unique RenderState objects allocated in the world.
static void flush_level()
Flushes the PStatCollectors used during traversal.
static int get_num_unused_states()
Returns the total number of RenderState objects that have been allocated but have no references outsi...
This object holds the camera position, etc., and other general setup information for rendering a part...
void set_world_transform(const TransformState *world_transform)
Specifies the position of the starting node relative to the camera.
void set_viewport_size(int width, int height)
Specifies the size of the viewport (display region), in pixels.
DisplayRegion * get_display_region() const
Returns the display region for the scene.
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...
const NodePath & get_scene_root() const
Returns the root node of the scene.
void set_scene_root(const NodePath &scene_root)
Specifies the root node of the scene.
void set_cs_transform(const TransformState *cs_transform)
Specifies the transform from the camera's coordinate system to the GSG's internal coordinate system.
void set_lens(const Lens *lens)
Indicates the particular Lens used for rendering.
void set_camera_path(const NodePath &camera_path)
Specifies the NodePath to the camera.
const NodePath & get_cull_center() const
Returns the point from which the culling operations will be performed.
void set_display_region(DisplayRegion *display_region)
Specifies the display region for the scene.
void set_camera_transform(const TransformState *camera_transform)
Specifies the position of the camera relative to the starting node.
void set_inverted(bool inverted)
Changes the current setting of the inverted flag.
void set_camera_node(Camera *camera_node)
Specifies the camera used to render the scene.
Filename get_filename(ShaderType type=ST_none) const
Return the Shader's filename for the given shader type.
size_t get_total_size() const
Returns the total size of all objects currently active on the LRU.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
get_image_modified
Returns a sequence number which is guaranteed to change at least every time the texture image data (i...
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general.
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...
static bool has_textures_power_2()
If true, then get_textures_power_2 has been set using set_textures_power_2.
A thread; that is, a lightweight process.
is_threading_supported
Returns true if threading support has been compiled in and enabled, or false if no threading is avail...
get_current_pipeline_stage
Returns the integer pipeline stage associated with the current thread.
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
is_true_threads
Returns true if a real threading library is available that supports actual OS-implemented threads,...
get_current_thread
Returns a pointer to the currently-executing Thread object.
static void prepare_for_exit()
Should be called by the main thread just before exiting the program, this blocks until any remaining ...
static void force_yield()
Suspends the current thread for the rest of the current epoch.
TypeHandle is the identifier used to differentiate C++ class types.
get_name
Returns the name of the type.
static SimpleLru * get_pending_lru()
Returns a pointer to the global LRU object that manages the VertexDataPage's that are pending process...
static void stop_threads()
Call this to stop the paging threads, if they were started.
static SimpleLru * get_global_lru(RamClass rclass)
Returns a pointer to the global LRU object that manages the VertexDataPage's with the indicated RamCl...
get_save_file
Returns the global VertexDataSaveFile that will be used to save vertex data buffers to disk when nece...
A temporary file to hold the vertex data that has been evicted from memory and written to disk.
size_t get_total_file_size() const
Returns the amount of space consumed by the save file, including unused portions.
size_t get_used_file_size() const
Returns the amount of space within the save file that is currently in use.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
has_size
Returns true if the window size has been specified, false otherwise.
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...
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
void swap(ordered_vector< Key, Compare, Vector > &other)
Exchanges the contents of this vector and the other vector, in constant time (e.g....
size_type_0 size() const
Returns the number of elements in the ordered vector.
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
void sort()
Maps to sort_unique().
bool verify_list() const
Maps to verify_list_unique().
This is our own Panda specialization on the default STL map.
This is our own Panda specialization on the default STL vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(Texture) GraphicsEngine
Called by DisplayRegion::do_get_screenshot.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.