15 #include "graphicsEngine.h"
16 #include "graphicsPipe.h"
17 #include "parasiteBuffer.h"
18 #include "config_gobj.h"
19 #include "config_display.h"
21 #include "drawCullHandler.h"
22 #include "binCullHandler.h"
23 #include "cullResult.h"
24 #include "cullTraverser.h"
25 #include "clockObject.h"
26 #include "pStatTimer.h"
27 #include "pStatGPUTimer.h"
28 #include "pStatClient.h"
29 #include "pStatCollector.h"
30 #include "mutexHolder.h"
31 #include "reMutexHolder.h"
32 #include "lightReMutexHolder.h"
33 #include "cullFaceAttrib.h"
34 #include "string_utils.h"
35 #include "geomCacheManager.h"
36 #include "renderState.h"
37 #include "transformState.h"
40 #include "throw_event.h"
42 #include "cullableObject.h"
43 #include "geomVertexArrayData.h"
44 #include "omniBoundingVolume.h"
45 #include "vertexDataSaveFile.h"
46 #include "vertexDataBook.h"
47 #include "vertexDataPage.h"
48 #include "config_pgraph.h"
49 #include "displayRegionCullCallbackData.h"
50 #include "displayRegionDrawCallbackData.h"
51 #include "callbackGraphicsWindow.h"
54 #define WINDOWS_LEAN_AND_MEAN
57 #undef WINDOWS_LEAN_AND_MEAN
138 if (_pipeline == (
Pipeline *)NULL) {
142 _windows_sorted =
true;
143 _window_sort_index = 0;
144 _needs_open_windows =
false;
147 if (!_threading_model.is_default()) {
149 <<
"Using threading model " << _threading_model <<
"\n";
151 _auto_flip = auto_flip;
152 _portal_enabled =
false;
153 _flip_state = FS_flip;
155 _singular_warning_last_frame =
false;
156 _singular_warning_this_frame =
false;
168 if (_app_pcollector.is_started()) {
169 _app_pcollector.stop();
187 display_cat.warning()
188 <<
"Threading model " << threading_model
189 <<
" requested but threading is not available. Ignoring.\n";
194 #ifndef THREADED_PIPELINE
196 display_cat.warning()
197 <<
"Threading model " << threading_model
198 <<
" requested but multithreaded render pipelines not enabled in build.\n";
199 if (!allow_nonpipeline_threads) {
200 display_cat.warning()
201 <<
"Ignoring requested threading model.\n";
204 display_cat.warning()
205 <<
"Danger! Creating requested render threads anyway!\n";
207 #endif // THREADED_PIPELINE
209 _threading_model = threading_model;
223 result = _threading_model;
249 const string &name,
int sort,
289 int x_size = 0, y_size = 0;
294 if ((x_size == 0)&&(y_size == 0)) {
295 flags |= GraphicsPipe::BF_size_track_host;
337 nassertr(pipe == gsg->
get_pipe(), NULL);
344 if ((flags & GraphicsPipe::BF_require_callback_window)!=0) {
349 this_gsg = pipe->make_callback_gsg(
this);
353 window->_sort = sort;
354 do_add_window(window, threading_model);
355 do_add_gsg(window->
get_gsg(), pipe, threading_model);
356 display_cat.info() <<
"Created output of type CallbackGraphicsWindow\n";
367 bool can_use_parasite =
false;
369 ((flags&GraphicsPipe::BF_require_window)==0)&&
370 ((flags&GraphicsPipe::BF_require_callback_window)==0)&&
371 ((flags&GraphicsPipe::BF_refuse_parasite)==0)&&
372 ((flags&GraphicsPipe::BF_can_bind_color)==0)&&
373 ((flags&GraphicsPipe::BF_can_bind_every)==0)&&
374 ((flags&GraphicsPipe::BF_rtt_cumulative)==0)&&
375 ((flags&GraphicsPipe::BF_can_bind_layered)==0)) {
376 if ((flags&GraphicsPipe::BF_fb_props_optional) ||
378 can_use_parasite =
true;
387 if ((prefer_parasite_buffer) &&
388 (can_use_parasite) &&
389 (x_size <= host->get_x_size())&&
390 (y_size <= host->get_y_size())&&
393 buffer->_sort = sort;
394 do_add_window(buffer, threading_model);
395 do_add_gsg(host->
get_gsg(), pipe, threading_model);
396 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
403 if (force_parasite_buffer && can_use_parasite) {
405 buffer->_sort = sort;
406 do_add_window(buffer, threading_model);
407 do_add_gsg(host->
get_gsg(), pipe, threading_model);
408 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
414 for (
int retry=0; retry<10; retry++) {
415 bool precertify =
false;
417 pipe->make_output(name, fb_prop, win_prop, flags,
this, gsg, host, retry, precertify);
419 window->_sort = sort;
420 if ((precertify) && (gsg != 0) && (window->get_gsg()==gsg)) {
421 do_add_window(window, threading_model);
422 do_add_gsg(window->get_gsg(), pipe, threading_model);
424 <<
"Created output of type " << window->get_type() <<
"\n";
427 do_add_window(window, threading_model);
429 if (window->is_valid()) {
430 do_add_gsg(window->get_gsg(), pipe, threading_model);
432 <<
"Created output of type " << window->get_type() <<
"\n";
434 if (window->get_fb_properties().subsumes(fb_prop)) {
437 if (flags & GraphicsPipe::BF_fb_props_optional) {
438 display_cat.warning()
439 <<
"FrameBufferProperties available less than requested.\n";
443 <<
"Could not get requested FrameBufferProperties; abandoning window.\n";
444 display_cat.error(
false)
445 <<
" requested: " << fb_prop <<
"\n"
446 <<
" got: " << window->get_fb_properties() <<
"\n";
450 << window->get_type() <<
" wouldn't open; abandoning.\n";
451 display_cat.debug(
false)
452 <<
" requested: " << fb_prop <<
"\n";
457 nassertr(removed, NULL);
465 if (can_use_parasite) {
467 buffer->_sort = sort;
468 do_add_window(buffer, threading_model);
469 do_add_gsg(host->
get_gsg(), pipe, threading_model);
470 display_cat.info() <<
"Created output of type ParasiteBuffer\n";
492 nassertr(window != NULL,
false);
495 nassertr(
this == window->
get_engine(),
false);
497 window->_sort = sort;
498 do_add_window(window, threading_model);
505 <<
"Added output of type " << window->get_type() <<
"\n";
541 nassertr(window != NULL,
false);
549 if (!_windows_sorted) {
552 count = _windows.erase(ptwin);
559 do_remove_window(window, current_thread);
567 bool any_common =
false;
570 Windows::iterator wi;
571 for (wi = _windows.
begin(); wi != _windows.
end() && !any_common; ++wi) {
591 nassertr(count == 1,
true);
612 old_windows.
swap(_windows);
613 Windows::iterator wi;
614 for (wi = old_windows.
begin(); wi != old_windows.
end(); ++wi) {
616 nassertv(win != NULL);
617 do_remove_window(win, current_thread);
624 _app.do_close(
this, current_thread);
625 _app.do_pending(
this, current_thread);
626 terminate_threads(current_thread);
641 PStatClient::get_global_pstats()->disconnect();
658 Windows::iterator wi;
659 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
675 return _windows.
empty();
686 return _windows.
size();
697 nassertr(n >= 0 && n < (
int)_windows.
size(), NULL);
699 if (!_windows_sorted) {
723 _render_frame_pcollector.start();
724 if (_app_pcollector.is_started()) {
725 _app_pcollector.stop();
729 if (_needs_open_windows) {
740 if (display_cat.is_spam()) {
742 <<
"render_frame() - frame " << global_clock->
get_frame_count() <<
"\n";
748 if (!_windows_sorted) {
752 if (sync_flip && _flip_state != FS_flip) {
753 do_flip_frame(current_thread);
759 Windows::iterator wi;
760 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
762 nassertv(win != NULL);
764 do_remove_window(win, current_thread);
776 for (
int i = 0; i < num_drs; ++i) {
783 if (scene.is_empty()) {
784 scene = camera_np.
get_top(current_thread);
786 if (!scene.is_empty()) {
787 scene.get_bounds(current_thread);
794 _windows.
swap(new_windows);
800 LoadedTextures::iterator lti;
801 for (lti = _loaded_textures.begin(); lti != _loaded_textures.end(); ++lti) {
802 LoadedTexture < = (*lti);
803 if (lt._tex->get_image_modified() == lt._image_modified) {
804 lt._tex->texture_uploaded();
807 _loaded_textures.clear();
812 _app.do_frame(
this, current_thread);
817 PStatTimer timer(_wait_pcollector, current_thread);
818 Threads::const_iterator ti;
819 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
820 RenderThread *thread = (*ti).second;
821 thread->_cv_mutex.acquire();
823 while (thread->_thread_state != TS_wait) {
824 thread->_cv_done.wait();
829 #if defined(THREADED_PIPELINE) && defined(DO_PSTATS)
830 _cyclers_pcollector.set_level(_pipeline->get_num_cyclers());
831 _dirty_cyclers_pcollector.set_level(_pipeline->get_num_dirty_cyclers());
835 _pipeline->iterate_all_cycler_types(pstats_count_cycler_type,
this);
836 _pipeline->iterate_dirty_cycler_types(pstats_count_dirty_cycler_type,
this);
838 #endif // DEBUG_THREADS
840 #endif // THREADED_PIPELINE && DO_PSTATS
845 TransformState::flush_level();
849 #ifdef THREADED_PIPELINE
851 PStatTimer timer(_cycle_pcollector, current_thread);
854 #endif // THREADED_PIPELINE
856 global_clock->
tick(current_thread);
858 throw_event(
"clock_error");
862 PStatClient::main_tick();
865 CullTraverser::_nodes_pcollector.clear_level();
866 CullTraverser::_geom_nodes_pcollector.clear_level();
867 CullTraverser::_geoms_pcollector.clear_level();
868 GeomCacheManager::_geom_cache_active_pcollector.clear_level();
869 GeomCacheManager::_geom_cache_record_pcollector.clear_level();
870 GeomCacheManager::_geom_cache_erase_pcollector.clear_level();
871 GeomCacheManager::_geom_cache_evict_pcollector.clear_level();
873 GraphicsStateGuardian::init_frame_pstats();
875 _transform_states_pcollector.set_level(TransformState::get_num_states());
877 if (pstats_unused_states) {
878 _transform_states_unused_pcollector.set_level(TransformState::get_num_unused_states());
882 _sw_sprites_pcollector.clear_level();
884 _cnode_volume_pcollector.clear_level();
885 _gnode_volume_pcollector.clear_level();
886 _geom_volume_pcollector.clear_level();
887 _node_volume_pcollector.clear_level();
888 _volume_pcollector.clear_level();
889 _test_pcollector.clear_level();
890 _volume_polygon_pcollector.clear_level();
891 _test_polygon_pcollector.clear_level();
892 _volume_plane_pcollector.clear_level();
893 _test_plane_pcollector.clear_level();
894 _volume_sphere_pcollector.clear_level();
895 _test_sphere_pcollector.clear_level();
896 _volume_box_pcollector.clear_level();
897 _test_box_pcollector.clear_level();
898 _volume_tube_pcollector.clear_level();
899 _test_tube_pcollector.clear_level();
900 _volume_inv_sphere_pcollector.clear_level();
901 _test_inv_sphere_pcollector.clear_level();
902 _volume_geom_pcollector.clear_level();
903 _test_geom_pcollector.clear_level();
904 _occlusion_untested_pcollector.clear_level();
905 _occlusion_passed_pcollector.clear_level();
906 _occlusion_failed_pcollector.clear_level();
907 _occlusion_tests_pcollector.clear_level();
920 _vertex_data_small_pcollector.set_level(small_buf);
921 _vertex_data_independent_pcollector.set_level(independent);
922 _vertex_data_pending_pcollector.set_level(pending);
923 _vertex_data_resident_pcollector.set_level(resident);
924 _vertex_data_compressed_pcollector.set_level(compressed);
925 _vertex_data_unused_disk_pcollector.set_level(total_disk - used_disk);
926 _vertex_data_used_disk_pcollector.set_level(used_disk);
934 Threads::const_iterator ti;
935 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
936 RenderThread *thread = (*ti).second;
937 if (thread->_thread_state == TS_wait) {
938 thread->_thread_state = TS_do_frame;
939 thread->_cv_start.notify();
941 thread->_cv_mutex.release();
946 _flip_state = _auto_flip ? FS_flip : FS_draw;
951 if (yield_timeslice) {
954 PStatTimer timer(_yield_pcollector, current_thread);
957 PStatTimer timer(_yield_pcollector, current_thread);
963 _app_pcollector.start();
964 _render_frame_pcollector.stop();
985 if (!_windows_sorted) {
991 for (
int i = 0; i < 2; ++i) {
992 _app.do_windows(
this, current_thread);
993 _app.do_pending(
this, current_thread);
995 PStatTimer timer(_wait_pcollector, current_thread);
996 Threads::const_iterator ti;
997 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
998 RenderThread *thread = (*ti).second;
999 thread->_cv_mutex.acquire();
1001 while (thread->_thread_state != TS_wait) {
1002 thread->_cv_done.wait();
1005 thread->_thread_state = TS_do_windows;
1006 thread->_cv_start.notify();
1007 thread->_cv_mutex.release();
1011 _needs_open_windows =
false;
1028 if (_flip_state == FS_draw) {
1029 do_sync_frame(current_thread);
1053 if (_flip_state == FS_draw) {
1054 do_ready_flip(current_thread);
1072 if (_flip_state != FS_flip) {
1073 do_flip_frame(current_thread);
1111 if (draw_name.empty()) {
1118 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1119 RenderThread *thread = (RenderThread *)wr;
1122 while (thread->_thread_state != TS_wait) {
1123 thread->_cv_done.wait();
1158 CPT(
RenderState) state = RenderState::make(sattr);
1161 if (draw_name.empty()) {
1167 WindowRenderer *wr = get_window_renderer(draw_name, 0);
1168 RenderThread *thread = (RenderThread *)wr;
1171 while (thread->_thread_state != TS_wait) {
1172 thread->_cv_done.wait();
1192 if (_global_ptr == NULL) {
1218 _loaded_textures.push_back(LoadedTexture());
1219 LoadedTexture < = _loaded_textures.back();
1240 trav->set_view_frustum(NULL);
1241 if (view_frustum_cull) {
1250 bv->is_of_type(GeometricBoundingVolume::get_class_type()) &&
1251 !bv->is_of_type(OmniBoundingVolume::get_class_type())) {
1257 CPT(TransformState) cull_center_transform =
1259 local_frustum->xform(cull_center_transform->get_mat());
1261 trav->set_view_frustum(local_frustum);
1266 trav->end_traverse();
1276 bool GraphicsEngine::
1277 scene_root_func(
const PandaNode *node) {
1278 return _global_ptr->is_scene_root(node);
1288 bool GraphicsEngine::
1292 Windows::const_iterator wi;
1293 for (wi = _windows.
begin(); wi != _windows.
end(); ++wi) {
1297 for (
int i = 0; i < num_display_regions; i++) {
1306 DCAST_INTO_R(camera_node, camera.
node(),
false);
1316 scene_root = camera.
get_top(current_thread);
1319 if (scene_root.
node() == node) {
1340 void GraphicsEngine::
1343 window->_sort = sort;
1344 _windows_sorted =
false;
1356 void GraphicsEngine::
1358 Thread *current_thread) {
1359 PStatTimer timer(_cull_pcollector, current_thread);
1361 size_t wlist_size = wlist.
size();
1362 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1367 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1371 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1376 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1377 win->
clear(current_thread);
1380 for (
int i = 0; i < num_display_regions; i++) {
1383 cull_and_draw_together(win, dr, current_thread);
1386 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1391 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1395 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1411 void GraphicsEngine::
1413 Thread *current_thread) {
1423 if (dr_reader->is_any_clear_active()) {
1427 PT(
SceneSetup) scene_setup = setup_scene(gsg, dr_reader);
1431 }
else if (dr_reader->get_object()->
is_stereo()) {
1434 }
else if (!gsg->
set_scene(scene_setup)) {
1437 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
1455 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1475 void GraphicsEngine::
1477 PStatTimer timer(_cull_pcollector, current_thread);
1479 _singular_warning_last_frame = _singular_warning_this_frame;
1480 _singular_warning_this_frame =
false;
1485 AlreadyCulled already_culled;
1487 size_t wlist_size = wlist.
size();
1488 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1493 for (
int i = 0; i < num_display_regions; ++i) {
1499 AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(camera, (
DisplayRegion *)NULL)).first;
1500 if ((*aci).second == NULL) {
1506 cull_to_bins(win, dr, current_thread);
1518 setup_scene(win->
get_gsg(), dr_reader),
1537 void GraphicsEngine::
1547 PStatTimer timer(_cull_setup_pcollector, current_thread);
1549 scene_setup = setup_scene(gsg, &dr_reader);
1553 cull_result = cull_result->make_next();
1573 dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
1576 PStatTimer timer(_cull_sort_pcollector, current_thread);
1577 cull_result->
finish_cull(scene_setup, current_thread);
1593 void GraphicsEngine::
1597 size_t wlist_size = wlist.
size();
1598 for (
size_t wi = 0; wi < wlist_size; ++wi) {
1609 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1613 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1618 if (win->
begin_frame(GraphicsOutput::FM_render, current_thread)) {
1623 win->
clear(current_thread);
1625 if (display_cat.is_spam()) {
1627 <<
"Drawing window " << win->
get_name() <<
"\n";
1630 for (
int i = 0; i < num_display_regions; ++i) {
1633 draw_bins(win, dr, current_thread);
1637 win->
end_frame(GraphicsOutput::FM_render, current_thread);
1643 win->
get_gsg()->issue_timer_query(GraphicsStateGuardian::_command_latency_pcollector.get_index());
1650 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1661 if (display_cat.is_spam()) {
1663 <<
"Not drawing window " << win->
get_name() <<
"\n";
1668 if (display_cat.is_spam()) {
1670 <<
"Window " << win->
get_name() <<
" is inactive\n";
1683 void GraphicsEngine::
1690 PT(
CullResult) cull_result = dr->get_cull_result(current_thread);
1691 PT(
SceneSetup) scene_setup = dr->get_scene_setup(current_thread);
1692 do_draw(cull_result, scene_setup, win, dr, current_thread);
1704 Windows::const_iterator wi;
1705 for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
1707 if (win->
begin_frame(GraphicsOutput::FM_refresh, current_thread)) {
1708 win->
end_frame(GraphicsOutput::FM_refresh, current_thread);
1720 void GraphicsEngine::
1725 for (
size_t i = 0; i < wlist.
size(); ++i) {
1726 wlist[i]->process_events();
1737 void GraphicsEngine::
1739 size_t num_windows = wlist.
size();
1741 size_t warray_count = 0;
1745 for (i = 0; i < num_windows; ++i) {
1748 nassertv(warray_count < num_windows);
1749 warray[warray_count] = win;
1752 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1757 for (i = 0; i < warray_count; ++i) {
1759 PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
1771 void GraphicsEngine::
1773 Windows::const_iterator wi;
1774 for (wi = wlist.
begin(); wi != wlist.
end(); ++wi) {
1777 PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
1789 void GraphicsEngine::
1790 do_sync_frame(
Thread *current_thread) {
1794 PStatTimer timer(_sync_pcollector, current_thread);
1796 nassertv(_flip_state == FS_draw);
1800 Threads::const_iterator ti;
1801 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1802 RenderThread *thread = (*ti).second;
1803 thread->_cv_mutex.acquire();
1804 thread->_cv_mutex.release();
1807 _flip_state = FS_sync;
1816 void GraphicsEngine::
1817 do_ready_flip(
Thread *current_thread) {
1821 PStatTimer timer(_sync_pcollector, current_thread);
1823 nassertv(_flip_state == FS_draw);
1827 Threads::const_iterator ti;
1828 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1829 RenderThread *thread = (*ti).second;
1830 thread->_cv_mutex.acquire();
1831 thread->_cv_mutex.release();
1833 _app.do_ready_flip(
this,current_thread);
1834 _flip_state = FS_sync;
1843 void GraphicsEngine::
1844 do_flip_frame(
Thread *current_thread) {
1848 PStatTimer timer(_flip_pcollector, current_thread);
1850 nassertv(_flip_state == FS_draw || _flip_state == FS_sync);
1856 PStatTimer timer(_wait_pcollector, current_thread);
1857 Threads::const_iterator ti;
1858 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1859 RenderThread *thread = (*ti).second;
1860 thread->_cv_mutex.acquire();
1862 while (thread->_thread_state != TS_wait) {
1863 thread->_cv_done.wait();
1869 _app.do_flip(
this, current_thread);
1872 Threads::const_iterator ti;
1873 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
1874 RenderThread *thread = (*ti).second;
1875 nassertv(thread->_thread_state == TS_wait);
1876 thread->_thread_state = TS_do_flip;
1877 thread->_cv_start.notify();
1878 thread->_cv_mutex.release();
1882 _flip_state = FS_flip;
1896 PStatTimer timer(_cull_setup_pcollector, current_thread);
1904 NodePath camera = dr->get_camera();
1911 DCAST_INTO_R(camera_node, camera.
node(), NULL);
1919 int lens_index = dr->get_lens_index();
1931 scene_root = camera.
get_top(current_thread);
1943 NodePath scene_parent = scene_root.get_parent(current_thread);
1944 CPT(TransformState) camera_transform = camera.get_transform(scene_parent, current_thread);
1945 CPT(TransformState) world_transform = scene_parent.get_transform(camera, current_thread);
1947 if (camera_transform->is_invalid()) {
1949 if (!_singular_warning_last_frame) {
1950 display_cat.warning()
1951 <<
"Scene " << scene_root <<
" has net scale ("
1953 _singular_warning_this_frame =
true;
1958 if (world_transform->is_invalid()) {
1960 if (!_singular_warning_last_frame) {
1961 display_cat.warning()
1962 <<
"Camera " << camera <<
" has net scale ("
1963 << camera.get_scale(
NodePath()) <<
"); cannot render.\n";
1965 _singular_warning_this_frame =
true;
1969 CPT(
RenderState) initial_state = camera_node->get_initial_state();
1971 if (window->get_inverted()) {
1975 scene_setup->set_inverted(
true);
1979 initial_state = initial_state->compose(get_invert_polygon_state());
1982 scene_setup->set_display_region(dr->get_object());
1983 scene_setup->set_viewport_size(dr->get_pixel_width(), dr->get_pixel_height());
1984 scene_setup->set_scene_root(scene_root);
1985 scene_setup->set_camera_path(camera);
1986 scene_setup->set_camera_node(camera_node);
1988 scene_setup->set_initial_state(initial_state);
1989 scene_setup->set_camera_transform(camera_transform);
1990 scene_setup->set_world_transform(world_transform);
1992 CPT(TransformState) cs_transform = gsg->get_cs_transform_for(lens->get_coordinate_system());
1993 scene_setup->set_cs_transform(cs_transform);
1995 CPT(TransformState) cs_world_transform = cs_transform->compose(world_transform);
1996 scene_setup->set_cs_world_transform(cs_world_transform);
2002 if (gsg->get_shader_generator() == NULL) {
2014 void GraphicsEngine::
2015 do_draw(
CullResult *cull_result, SceneSetup *scene_setup,
2028 if (dr_reader.is_any_clear_active()) {
2029 gsg->
clear(dr_reader.get_object());
2052 if (cull_result == NULL || scene_setup == NULL) {
2063 }
else if (!gsg->
set_scene(scene_setup)) {
2066 << gsg->get_type() <<
" cannot render scene with specified lens.\n";
2070 cull_result->
draw(current_thread);
2085 void GraphicsEngine::
2088 nassertv(window != NULL);
2095 window->_internal_sort_index = _window_sort_index;
2096 ++_window_sort_index;
2098 _windows_sorted =
false;
2101 WindowRenderer *cull =
2104 WindowRenderer *draw =
2109 cull->add_window(cull->_cull, window);
2110 draw->add_window(draw->_draw, window);
2112 cull->add_window(cull->_cdraw, window);
2126 case GraphicsPipe::PWT_app:
2127 _app.add_window(_app._window, window);
2130 case GraphicsPipe::PWT_draw:
2131 draw->add_window(draw->_window, window);
2135 if (display_cat.is_debug()) {
2137 <<
"Created " << window->get_type() <<
" " << (
void *)window <<
"\n";
2141 _needs_open_windows =
true;
2152 void GraphicsEngine::
2155 nassertv(gsg != NULL);
2159 gsg->_threading_model = threading_model;
2160 if (!_default_loader.is_null()) {
2164 auto_adjust_capabilities(gsg);
2166 WindowRenderer *draw =
2181 void GraphicsEngine::
2183 nassertv(window != NULL);
2185 window->clear_pipe();
2187 if (!_windows_sorted) {
2188 do_resort_windows();
2192 _app.remove_window(window);
2193 Threads::const_iterator ti;
2194 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2195 RenderThread *thread = (*ti).second;
2196 thread->remove_window(window);
2201 _app.do_pending(
this, current_thread);
2203 if (display_cat.is_debug()) {
2205 <<
"Removed " << window->get_type() <<
" " << (
void *)window <<
"\n";
2216 void GraphicsEngine::
2217 do_resort_windows() {
2218 _windows_sorted =
true;
2220 _app.resort_windows();
2221 Threads::const_iterator ti;
2222 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2223 RenderThread *thread = (*ti).second;
2224 thread->resort_windows();
2259 void GraphicsEngine::
2290 if (textures_auto_power_2 && (textures_power_2 == ATS_none)) {
2292 <<
"Invalid panda config file: if you set the config-variable\n"
2293 <<
"textures_auto_power_2 to true, you must set the config-variable"
2294 <<
"textures_power_2 to 'up' or 'down'.\n";
2295 textures_power_2 = ATS_down;
2312 <<
"The 'textures_power_2' configuration is set to 'none', meaning \n"
2313 <<
"that non-power-of-two texture support is required, but the video \n"
2314 <<
"driver I'm trying to use does not support non-power-of-two textures.\n";
2316 if (textures_power_2 != ATS_none) {
2318 <<
"The 'none' did not come from the config file. In other words,\n"
2319 <<
"the variable 'textures_power_2' was altered procedurally.\n";
2321 if (textures_auto_power_2) {
2323 <<
"It is possible that it was set by panda's automatic mechanisms,\n"
2324 <<
"which are currently enabled, because 'textures_auto_power_2' is\n"
2325 <<
"true. Panda's automatic mechanisms assume that if one\n"
2326 <<
"window supports non-power-of-two textures, then they all will.\n"
2327 <<
"This assumption works for most games, but not all.\n"
2328 <<
"In particular, it can fail if the game creates multiple windows\n"
2329 <<
"on multiple displays with different video cards.\n";
2334 if (shader_auto_utilization && (shader_utilization != SUT_none)) {
2336 <<
"Invalid panda config file: if you set the config-variable\n"
2337 <<
"shader_auto_utilization to true, you must set the config-variable"
2338 <<
"shader_utilization to 'none'.\n";
2339 shader_utilization = SUT_none;
2356 <<
"The 'shader_utilization' config variable is set, meaning\n"
2357 <<
"that panda may try to generate shaders. However, the video \n"
2358 <<
"driver I'm trying to use does not support shaders.\n";
2360 if (shader_utilization == SUT_none) {
2362 <<
"The 'shader_utilization' setting did not come from the config\n"
2363 <<
"file. In other words, it was altered procedurally.\n";
2365 if (shader_auto_utilization) {
2367 <<
"It is possible that it was set by panda's automatic mechanisms,\n"
2368 <<
"which are currently enabled, because 'shader_auto_utilization' is\n"
2369 <<
"true. Panda's automatic mechanisms assume that if one\n"
2370 <<
"window supports shaders, then they all will.\n"
2371 <<
"This assumption works for most games, but not all.\n"
2372 <<
"In particular, it can fail if the game creates multiple windows\n"
2373 <<
"on multiple displays with different video cards.\n";
2385 void GraphicsEngine::
2386 terminate_threads(
Thread *current_thread) {
2391 PStatTimer timer(_wait_pcollector, current_thread);
2395 Threads::const_iterator ti;
2396 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2397 RenderThread *thread = (*ti).second;
2398 thread->_cv_mutex.acquire();
2402 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2403 RenderThread *thread = (*ti).second;
2404 thread->_thread_state = TS_terminate;
2405 thread->_cv_start.notify();
2406 thread->_cv_mutex.release();
2410 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
2411 RenderThread *thread = (*ti).second;
2427 void GraphicsEngine::
2428 pstats_count_cycler_type(
TypeHandle type,
int count,
void *data) {
2430 CyclerTypeCounters::iterator ci =
self->_all_cycler_types.find(type);
2431 if (ci == self->_all_cycler_types.end()) {
2433 ci =
self->_all_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2435 (*ci).second.set_level(count);
2447 void GraphicsEngine::
2448 pstats_count_dirty_cycler_type(
TypeHandle type,
int count,
void *data) {
2450 CyclerTypeCounters::iterator ci =
self->_dirty_cycler_types.find(type);
2451 if (ci == self->_dirty_cycler_types.end()) {
2453 ci =
self->_dirty_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
2455 (*ci).second.set_level(count);
2468 get_invert_polygon_state() {
2473 state = RenderState::make(CullFaceAttrib::make_reverse());
2491 GraphicsEngine::WindowRenderer *GraphicsEngine::
2492 get_window_renderer(
const string &name,
int pipeline_stage) {
2499 Threads::iterator ti = _threads.find(name);
2500 if (ti != _threads.end()) {
2501 return (*ti).second.p();
2504 PT(RenderThread) thread = new RenderThread(name, this);
2505 thread->set_min_pipeline_stage(pipeline_stage);
2506 _pipeline->set_min_stages(pipeline_stage + 1);
2508 bool started = thread->start(TP_normal, true);
2509 nassertr(started, thread.p());
2510 _threads[name] = thread;
2512 nassertr(thread->get_pipeline_stage() < _pipeline->get_num_stages(), thread.p());
2523 WindowRenderer(const
string &name) :
2524 _wl_lock(
string("
GraphicsEngine::WindowRenderer::_wl_lock ") + name)
2534 void GraphicsEngine::WindowRenderer::
2546 void GraphicsEngine::WindowRenderer::
2549 wlist.insert(window);
2560 void GraphicsEngine::WindowRenderer::
2562 nassertv(window != NULL);
2567 _cdraw.erase(ptwin);
2570 Windows::iterator wi;
2572 wi = _window.find(ptwin);
2573 if (wi != _window.end()) {
2584 if (ptwin->is_valid()) {
2585 _pending_close.push_back(ptwin);
2598 void GraphicsEngine::WindowRenderer::
2607 if (display_cat.is_debug()) {
2609 <<
"Windows resorted:";
2610 Windows::const_iterator wi;
2611 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2613 display_cat.debug(
false)
2616 display_cat.debug(
false)
2619 for (wi = _draw.begin(); wi != _draw.end(); ++wi) {
2621 display_cat.debug(
false)
2624 display_cat.debug(
false)
2637 void GraphicsEngine::WindowRenderer::
2639 PStatTimer timer(engine->_do_frame_pcollector, current_thread);
2642 engine->cull_to_bins(_cull, current_thread);
2643 engine->cull_and_draw_together(_cdraw, current_thread);
2644 engine->draw_bins(_draw, current_thread);
2645 engine->process_events(_window, current_thread);
2649 if (any_done_gsgs()) {
2652 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2657 engine->close_gsg(pipe, gsg);
2660 new_gsgs.insert(gsg);
2664 _gsgs.swap(new_gsgs);
2677 void GraphicsEngine::WindowRenderer::
2681 engine->process_events(_window, current_thread);
2683 engine->make_contexts(_cdraw, current_thread);
2684 engine->make_contexts(_draw, current_thread);
2693 void GraphicsEngine::WindowRenderer::
2696 engine->flip_windows(_cdraw, current_thread);
2697 engine->flip_windows(_draw, current_thread);
2706 void GraphicsEngine::WindowRenderer::
2709 engine->ready_flip_windows(_cdraw, current_thread);
2710 engine->ready_flip_windows(_draw, current_thread);
2719 void GraphicsEngine::WindowRenderer::
2722 Windows::iterator wi;
2723 for (wi = _window.begin(); wi != _window.end(); ++wi) {
2731 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2736 engine->close_gsg(pipe, gsg);
2739 new_gsgs.insert(gsg);
2743 _gsgs.swap(new_gsgs);
2752 void GraphicsEngine::WindowRenderer::
2756 if (!_pending_close.empty()) {
2757 if (display_cat.is_debug()) {
2759 <<
"_pending_close.size() = " << _pending_close.size() <<
"\n";
2765 Windows::iterator wi;
2766 Windows pending_close;
2767 _pending_close.
swap(pending_close);
2768 for (wi = pending_close.begin(); wi != pending_close.end(); ++wi) {
2783 bool GraphicsEngine::WindowRenderer::
2784 any_done_gsgs()
const {
2785 GSGs::const_iterator gi;
2786 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
2787 if ((*gi)->get_ref_count() == 1) {
2800 GraphicsEngine::RenderThread::
2803 WindowRenderer(name),
2805 _cv_mutex(string(
"GraphicsEngine::RenderThread ") + name),
2806 _cv_start(_cv_mutex),
2809 _thread_state = TS_wait;
2819 void GraphicsEngine::RenderThread::
2825 nassertv(_cv_mutex.debug_is_locked());
2827 switch (_thread_state) {
2832 do_pending(_engine, current_thread);
2833 do_frame(_engine, current_thread);
2837 do_flip(_engine, current_thread);
2841 do_pending(_engine, current_thread);
2845 do_windows(_engine, current_thread);
2846 do_pending(_engine, current_thread);
2850 do_pending(_engine, current_thread);
2851 do_close(_engine, current_thread);
2852 _thread_state = TS_done;
2862 _thread_state = TS_wait;
2866 PStatTimer timer(_wait_pcollector, current_thread);
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.
const NodePath & get_scene() const
Returns the scene that will be rendered by the camera.
void tick(Thread *current_thread=Thread::get_current_thread())
Instructs the clock that a new frame has just begun.
int cleanup_aux_scene_data(Thread *current_thread=Thread::get_current_thread())
Walks through the list of currently-assigned AuxSceneData objects and releases any that are past thei...
virtual void request_close()
This is called by the GraphicsEngine to request that the window (or whatever) close itself or...
A basic node of the scene graph or data graph.
static void set_textures_power_2(AutoTextureScale scale)
Set this flag to ATS_none, ATS_up, ATS_down, or ATS_pad to control the scaling of textures in general...
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
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.
size_t get_total_size() const
Returns the total size of all objects currently active on the LRU.
virtual GraphicsOutput * get_host()
This is normally called only from within make_texture_buffer().
void set_loader(Loader *loader)
Sets the Loader object that will be used by this GSG to load textures when necessary, if get_incomplete_render() is true.
static void set_shader_utilization(ShaderUtilization utl)
Set this flag to SUT_none, SUT_basic, or SUT_advanced to limit panda's automatic shader generation fa...
static void flush_level()
Flushes the PStatCollectors used during traversal.
bool verify_list() const
Maps to verify_list_unique().
virtual void clear_before_callback()
Resets any non-standard graphics state that might give a callback apoplexy.
static bool have_shader_utilization()
If true, then get_shader_utilization has been set using set_shader_utilization.
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
void flip_frame()
Waits for all the threads that started drawing their last frame to finish drawing, and then flips all the windows.
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.
static VertexDataSaveFile * get_save_file()
Returns the global VertexDataSaveFile that will be used to save vertex data buffers to disk when nece...
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
bool get_incomplete_render() const
Returns the incomplete_render flag.
virtual bool is_stereo() const
Returns true if this is a StereoDisplayRegion, false otherwise.
NodePath get_parent(Thread *current_thread=Thread::get_current_thread()) const
Returns the NodePath to the parent of the referenced node: that is, this NodePath, shortened by one node.
void change_scenes(DisplayRegionPipelineReader *new_dr)
Called by the GraphicsEngine when the window is about to change to another DisplayRegion.
virtual PreferredWindowThread get_preferred_window_thread() const
Returns an indication of the thread in which this GraphicsPipe requires its window processing to be p...
void set_lens(Lens *lens)
Sets up the LensNode using this particular Lens pointer.
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
static void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup, GraphicsStateGuardian *gsg, Thread *current_thread)
Fires off a cull traversal using the indicated camera.
static void consider_flush_global_index()
If there is a global BamCache object, calls consider_flush_index() on it.
The abstract base class for all things that can collide with other things in the world, and all the things they can collide with (except geometry).
void release_all()
Releases all prepared objects.
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...
size_t get_used_file_size() const
Returns the amount of space within the save file that is currently in use.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
static bool is_true_threads()
Returns true if a real threading library is available that supports actual OS-implemented threads...
GraphicsOutput * get_window(int n) const
Returns the nth window or buffers managed by the engine, in sorted order.
A cuboid collision volume or object.
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...
string get_name(TypedObject *object=(TypedObject *) NULL) const
Returns the name of the type.
int get_num_active_display_regions() const
Returns the number of active DisplayRegions that have been created within the window.
bool is_active() const
Returns the active flag associated with the GraphicsStateGuardian.
CallbackObject * get_cull_callback() const
Returns the CallbackObject set by set_cull_callback().
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.
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
GraphicsPipe * get_pipe() const
Returns the graphics pipe on which this GSG was created.
bool is_valid() const
Returns true if the GSG has been correctly initialized within a graphics context, false if there has ...
PandaNode * node() const
Returns the referenced node of the path.
static ShaderUtilization get_shader_utilization()
This flag returns SUT_none, SUT_basic, or SUT_advanced and controls the automatic generation of shade...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
int get_cull_stage() const
Returns the pipeline stage from which the cull thread should access data.
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 ...
A spherical collision volume or object.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
static void flush_level()
Flushes the PStatCollectors used during traversal.
bool get_timer_queries_active() const
Returns true if timer queries are currently enabled on this GSG.
static SimpleLru * get_global_lru(RamClass rclass)
Returns a pointer to the global LRU object that manages the VertexDataPage's with the indicated RamCl...
DisplayRegion * get_display_region() const
Returns the display region for the scene.
bool remove_window(GraphicsOutput *window)
Removes the indicated window or offscreen buffer from the set of windows that will be processed when ...
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
void reserve(size_type_0 n)
Informs the vector of a planned change in size; ensures that the capacity of the vector is greater th...
A table of objects that are saved within the graphics context for reference by handle later...
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame...
static void lru_epoch()
Marks that an epoch has passed in each LRU.
This specialization on CallbackData is passed when the callback is initiated from the cull traversal...
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
const NodePath & get_scene_root() const
Returns the root node of the scene.
static void force_yield()
Suspends the current thread for the rest of the current epoch.
GraphicsEngine * get_engine() const
Returns the graphics engine that created this output.
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
void ready_flip()
Waits for all the threads that started drawing their last frame to finish drawing.
void texture_uploaded(Texture *tex)
This method is called by the GraphicsStateGuardian after a texture has been successfully uploaded to ...
void set_cull_result(CullResult *cull_result, SceneSetup *scene_setup, Thread *current_thread)
Stores the result of performing a cull operation on this DisplayRegion.
GraphicsPipe * get_pipe() const
Returns the GraphicsPipe that this window is associated with.
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...
PStatCollector & get_cull_region_pcollector()
Returns a PStatCollector for timing the cull operation for just this DisplayRegion.
bool is_valid() const
Returns true if the output is fully created and ready for rendering, false otherwise.
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...
bool get_lens_active(int index) const
Returns the active flag for the nth lens.
~GraphicsEngine()
Gracefully cleans up the graphics engine and its related threads and windows.
static bool is_threading_supported()
Returns true if threading support has been compiled in and enabled, or false if no threading is avail...
A lightweight class that represents a single element that may be timed and/or counted via stats...
virtual void set_state_and_transform(const RenderState *state, const TransformState *transform)
Simultaneously resets the render state and the transform state.
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general...
virtual void do_callback(CallbackData *cbdata)
This method called when the callback is triggered; it replaces* the original function.
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
virtual void set_close_now()
This is called by the GraphicsEngine to insist that the output be closed immediately.
void cycle()
Flows all the pipeline data down to the next stage.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
bool get_cull_sorting() const
Returns true if the model involves a separate cull pass, or false if culling happens implicitly...
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...
bool is_active() const
Returns the current setting of the active flag on the camera.
void clear(Thread *current_thread)
Clears the entire framebuffer before rendering, according to the settings of get_color_clear_active()...
void stop_threads()
Stops any threads that are currently running.
bool is_empty() const
Returns true if there are no windows or buffers managed by the engine, false if there is at least one...
CullResult * get_cull_result(Thread *current_thread) const
Returns the CullResult value that was stored on this DisplayRegion, presumably by the last successful...
This defines the abstract interface for an object that receives Geoms identified by the CullTraverser...
int get_sort() const
Returns the sorting order of this particular GraphicsOutput.
bool get_supports_basic_shaders() const
Returns true if this particular GSG supports arbfp1+arbvp1 or above.
This is a special GraphicsOutput type that acts a lot like a GraphicsBuffer, effectively allowing ren...
int get_draw_stage() const
Returns the pipeline stage from which the draw thread should access data.
virtual void clear_state_and_transform()
Forgets the current graphics state and current transform, so that the next call to set_state_and_tran...
const string & get_cull_name() const
Returns the name of the thread that will handle culling in this model.
GraphicsEngine(Pipeline *pipeline=NULL)
Creates a new GraphicsEngine object.
void sync_frame()
Waits for all the threads that started drawing their last frame to finish drawing.
virtual PreparedGraphicsObjects * get_prepared_objects()
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
A ClockObject keeps track of elapsed real time and discrete time.
static int get_num_unused_states()
Returns the total number of RenderState objects that have been allocated but have no references outsi...
bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg)
Asks the indicated GraphicsStateGuardian to retrieve the texture memory image of the indicated textur...
static SimpleLru * get_pending_lru()
Returns a pointer to the global LRU object that manages the VertexDataPage's that are pending process...
An object to create GraphicsOutputs that share a particular 3-D API.
int get_frame_count(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of times tick() has been called since the ClockObject was created, or since it was last reset.
PStatCollector & get_draw_region_pcollector()
Returns a PStatCollector for timing the draw operation for just this DisplayRegion.
void sort()
Maps to sort_unique().
static GraphicsStateGuardianBase * get_gsg(int n)
Returns the nth GSG in the universe.
The ShaderGenerator is a device that effectively replaces the classic fixed function pipeline with a ...
A container for geometry primitives.
const string & get_draw_name() const
Returns the name of the thread that will handle sending the actual graphics primitives to the graphic...
LVecBase3 get_scale() const
Retrieves the scale component of the transform.
This CullHandler sends all of the geoms it receives into a CullResult object, for binning (and later ...
UpdateSeq get_image_modified() const
Returns a sequence number which is guaranteed to change at least every time the texture image data (i...
GraphicsStateGuardian * get_gsg() const
Returns the GSG that is associated with this window.
bool get_supports_tex_non_pow2() const
Returns true if this GSG can handle non power of two sized textures.
A special CollisionPolygon created just for the purpose of detecting collision against geometry...
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...
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...
CallbackObject * get_draw_callback() const
Returns the CallbackObject set by set_draw_callback().
const NodePath & get_cull_center() const
Returns the point from which the culling operations will be performed.
This is a base class for the various different classes that represent the result of a frame of render...
Similar to MutexHolder, but for a light reentrant mutex.
GraphicsOutput * make_output(GraphicsPipe *pipe, const string &name, int sort, const FrameBufferProperties &fb_prop, const WindowProperties &win_prop, int flags, GraphicsStateGuardian *gsg=NULL, GraphicsOutput *host=NULL)
Creates a new window (or buffer) and returns it.
This represents the user's specification of how a particular frame is handled by the various threads...
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
This class manages a staged pipeline of data, for instance the render pipeline, so that each stage of...
virtual void reset_window(bool swapchain)
Resets the window framebuffer from its derived children.
void remove_all_windows()
Removes and closes all windows from the engine.
This is a generic object that can be assigned to a callback at various points in the rendering proces...
bool has_size() const
Returns true if the window size has been specified, false otherwise.
virtual void ready_flip()
This function will be called within the draw thread after end_frame() has been called on all windows...
This is the base class for all three-component vectors and points.
void render_frame()
Renders the next frame in all the registered windows, and flips all of the frame buffers.
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins, each of which holds a number of Geoms and RenderStates to be rendered in some defined order.
static void stop_threads()
Call this to stop the paging threads, if they were started.
static SimpleLru * get_independent_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that have not (yet)...
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
bool needs_reset() const
Returns true if the gsg is marked as needing a reset.
This special kind of CullHandler immediately draws its contents as soon as it receives them...
NodePath get_camera() const
Returns the camera associated with this DisplayRegion, or an empty NodePath if no camera is associate...
bool get_delete_flag() const
Returns the current setting of the delete flag.
bool is_single_threaded() const
Returns true if the threading model is a single-threaded model, or false if it involves threads...
GraphicsThreadingModel get_threading_model() const
Returns the threading model that will be applied to future objects.
A thread; that is, a lightweight process.
virtual bool flip_ready() const
Returns true if a frame has been rendered and needs to be flipped, false otherwise.
A node in the scene graph that can hold any number of CollisionSolids.
virtual void begin_flip()
This function will be called within the draw thread after end_frame() has been called on all windows...
size_t get_total_file_size() const
Returns the amount of space consumed by the save file, including unused portions. ...
Encapsulates all the communication with a particular instance of a given rendering backend...
static void flush_level()
Flushes the PStatCollectors used during traversal.
bool is_empty() const
Returns true if the NodePath contains no nodes.
virtual void end_scene()
Called between begin_frame() and end_frame() to mark the end of drawing commands for a "scene" (usual...
static bool is_connected()
Returns true if the client believes it is connected to a working PStatServer, false otherwise...
CullTraverser * get_cull_traverser()
Returns the CullTraverser that will be used to draw the contents of this DisplayRegion.
size_type_0 size() const
Returns the number of elements in the ordered vector.
A rectangular subregion within a window for rendering into.
bool debug_is_locked() const
Returns true if the current thread has locked the ReMutex, false otherwise.
void set_threading_model(const GraphicsThreadingModel &threading_model)
Specifies how future objects created via make_gsg(), make_buffer(), and make_window() will be threade...
const GraphicsThreadingModel & get_threading_model() const
Returns the threading model that was used to create this GSG.
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
void draw(Thread *current_thread)
Asks all the bins to draw themselves in the correct order.
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.
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
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.
int get_num_windows() const
Returns the number of windows (or buffers) managed by the engine.
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...
const string & get_name() const
Returns the name that was passed to the GraphicsOutput constructor.
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
bool set_scene(SceneSetup *scene_setup)
Sets the SceneSetup object that indicates the initial camera position, etc.
This implements a solid roughly in cylindrical shape.
int get_ref_count() const
Returns the current reference count.
static AsyncTaskManager * get_global_ptr()
Returns a pointer to the global AsyncTaskManager.
NodePath get_camera(Thread *current_thread=Thread::get_current_thread()) const
Returns the camera associated with this DisplayRegion, or an empty NodePath if no camera is associate...
virtual bool is_active() const
Returns true if the window is ready to be rendered into, 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...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
A node that holds Geom objects, renderable pieces of geometry.
virtual bool begin_scene()
Called between begin_frame() and end_frame() to mark the beginning of drawing commands for a "scene" ...
An inverted sphere: this is a sphere whose collision surface is the inside surface of the sphere...
void release_all()
Releases all prepared objects of all kinds at once.
void set_cull_handler(CullHandler *cull_handler)
Specifies the object that will receive the culled Geoms.
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...