00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "graphicsEngine.h"
00020 #include "graphicsPipe.h"
00021 #include "config_display.h"
00022 #include "pipeline.h"
00023 #include "drawCullHandler.h"
00024 #include "binCullHandler.h"
00025 #include "cullResult.h"
00026 #include "cullTraverser.h"
00027 #include "clockObject.h"
00028 #include "pStatTimer.h"
00029 #include "pStatClient.h"
00030 #include "mutexHolder.h"
00031 #include "string_utils.h"
00032
00033 #ifndef CPPPARSER
00034 PStatCollector GraphicsEngine::_cull_pcollector("Cull");
00035 PStatCollector GraphicsEngine::_draw_pcollector("Draw");
00036 #endif // CPPPARSER
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 GraphicsEngine::
00047 GraphicsEngine(Pipeline *pipeline) :
00048 _pipeline(pipeline)
00049 {
00050 if (_pipeline == (Pipeline *)NULL) {
00051 _pipeline = Pipeline::get_render_pipeline();
00052 }
00053
00054
00055 _frame_buffer_properties.set_depth_bits(1);
00056 _frame_buffer_properties.set_color_bits(1);
00057 _frame_buffer_properties.set_frame_buffer_mode
00058 (FrameBufferProperties::FM_rgba |
00059 FrameBufferProperties::FM_double_buffer |
00060 FrameBufferProperties::FM_depth);
00061
00062 set_threading_model(GraphicsThreadingModel(threading_model));
00063 if (!_threading_model.is_default()) {
00064 display_cat.info()
00065 << "Using threading model " << _threading_model << "\n";
00066 }
00067 _auto_flip = auto_flip;
00068 _flip_state = FS_flip;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077 GraphicsEngine::
00078 ~GraphicsEngine() {
00079 remove_all_windows();
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089 void GraphicsEngine::
00090 set_frame_buffer_properties(const FrameBufferProperties &properties) {
00091 MutexHolder holder(_lock);
00092 _frame_buffer_properties = properties;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101 FrameBufferProperties GraphicsEngine::
00102 get_frame_buffer_properties() const {
00103 FrameBufferProperties result;
00104 {
00105 MutexHolder holder(_lock);
00106 result = _frame_buffer_properties;
00107 }
00108 return result;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118 void GraphicsEngine::
00119 set_threading_model(const GraphicsThreadingModel &threading_model) {
00120 if (!threading_model.is_single_threaded() &&
00121 !Thread::is_threading_supported()) {
00122 display_cat.warning()
00123 << "Threading model " << threading_model
00124 << " requested but threading not supported.\n";
00125 return;
00126 }
00127 MutexHolder holder(_lock);
00128 _threading_model = threading_model;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 GraphicsThreadingModel GraphicsEngine::
00138 get_threading_model() const {
00139 GraphicsThreadingModel result;
00140 {
00141 MutexHolder holder(_lock);
00142 result = _threading_model;
00143 }
00144 return result;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 PT(GraphicsStateGuardian) GraphicsEngine::
00164 make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties,
00165 const GraphicsThreadingModel &threading_model) {
00166
00167 PT(GraphicsStateGuardian) gsg = pipe->make_gsg(properties);
00168 if (gsg != (GraphicsStateGuardian *)NULL) {
00169 gsg->_threading_model = threading_model;
00170 gsg->_pipe = pipe;
00171 }
00172
00173 return gsg;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 GraphicsWindow *GraphicsEngine::
00186 make_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
00187 const GraphicsThreadingModel &threading_model) {
00188 if (gsg != (GraphicsStateGuardian *)NULL) {
00189 nassertr(pipe == gsg->get_pipe(), NULL);
00190 nassertr(threading_model.get_draw_name() ==
00191 gsg->get_threading_model().get_draw_name(), NULL);
00192 }
00193
00194
00195 PT(GraphicsWindow) window = pipe->make_window(gsg);
00196 if (window != (GraphicsWindow *)NULL) {
00197 MutexHolder holder(_lock);
00198 _windows.insert(window);
00199
00200 WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name());
00201 WindowRenderer *draw = get_window_renderer(threading_model.get_draw_name());
00202 draw->add_gsg(gsg);
00203
00204 if (threading_model.get_cull_sorting()) {
00205 cull->add_window(cull->_cull, window);
00206 draw->add_window(draw->_draw, window);
00207 } else {
00208 cull->add_window(cull->_cdraw, window);
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 _app.add_window(_app._window, window);
00218
00219 display_cat.info()
00220 << "Created " << window->get_type() << "\n";
00221 }
00222 return window;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 bool GraphicsEngine::
00250 remove_window(GraphicsWindow *window) {
00251
00252 PT(GraphicsWindow) ptwin = window;
00253 size_t count;
00254 {
00255 MutexHolder holder(_lock);
00256 count = _windows.erase(ptwin);
00257 }
00258 if (count == 0) {
00259
00260 return false;
00261 }
00262
00263 do_remove_window(window);
00264 return true;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274 void GraphicsEngine::
00275 remove_all_windows() {
00276 Windows::iterator wi;
00277 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00278 GraphicsWindow *win = (*wi);
00279 do_remove_window(win);
00280 }
00281
00282 _windows.clear();
00283
00284 _app.do_release(this);
00285 _app.do_close(this);
00286 terminate_threads();
00287 }
00288
00289
00290
00291
00292
00293
00294
00295 bool GraphicsEngine::
00296 is_empty() const {
00297 return _windows.empty();
00298 }
00299
00300
00301
00302
00303
00304
00305
00306 void GraphicsEngine::
00307 render_frame() {
00308
00309
00310
00311
00312 MutexHolder holder(_lock);
00313
00314 if (_flip_state != FS_flip) {
00315 do_flip_frame();
00316 }
00317
00318
00319 Threads::const_iterator ti;
00320 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00321 RenderThread *thread = (*ti).second;
00322 thread->_cv_mutex.lock();
00323 }
00324
00325
00326 _pipeline->cycle();
00327 ClockObject::get_global_clock()->tick();
00328 PStatClient::main_tick();
00329
00330
00331 _app.do_frame(this);
00332 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00333 RenderThread *thread = (*ti).second;
00334 if (thread->_thread_state == TS_wait) {
00335 thread->_thread_state = TS_do_frame;
00336 thread->_cv.signal();
00337 }
00338 thread->_cv_mutex.release();
00339 }
00340
00341
00342
00343 _flip_state = FS_draw;
00344
00345
00346
00347 if (_threads.empty() && _auto_flip) {
00348 do_flip_frame();
00349 }
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 void GraphicsEngine::
00362 sync_frame() {
00363 MutexHolder holder(_lock);
00364
00365 if (_flip_state == FS_draw) {
00366 do_sync_frame();
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 void GraphicsEngine::
00380 flip_frame() {
00381 MutexHolder holder(_lock);
00382
00383 if (_flip_state != FS_flip) {
00384 do_flip_frame();
00385 }
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 void GraphicsEngine::
00404 render_subframe(GraphicsStateGuardian *gsg, DisplayRegion *dr,
00405 bool cull_sorting) {
00406 if (cull_sorting) {
00407 cull_bin_draw(gsg, dr);
00408 } else {
00409 cull_and_draw_together(gsg, dr);
00410 }
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 void GraphicsEngine::
00423 cull_and_draw_together(const GraphicsEngine::Windows &wlist) {
00424 Windows::const_iterator wi;
00425 for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
00426 GraphicsWindow *win = (*wi);
00427 if (win->is_active()) {
00428 if (win->begin_frame()) {
00429 win->clear();
00430
00431 int num_display_regions = win->get_num_display_regions();
00432 for (int i = 0; i < num_display_regions; i++) {
00433 DisplayRegion *dr = win->get_display_region(i);
00434 cull_and_draw_together(win->get_gsg(), dr);
00435 }
00436 win->end_frame();
00437 }
00438 }
00439 }
00440 }
00441
00442
00443
00444
00445
00446
00447
00448 void GraphicsEngine::
00449 cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
00450 nassertv(gsg != (GraphicsStateGuardian *)NULL);
00451
00452 PT(SceneSetup) scene_setup = setup_scene(dr->get_camera(), gsg);
00453 if (setup_gsg(gsg, scene_setup)) {
00454 DisplayRegionStack old_dr = gsg->push_display_region(dr);
00455 gsg->prepare_display_region();
00456 if (dr->is_any_clear_active()) {
00457 gsg->clear(dr);
00458 }
00459
00460 DrawCullHandler cull_handler(gsg);
00461 if (gsg->begin_scene()) {
00462 do_cull(&cull_handler, scene_setup, gsg);
00463 gsg->end_scene();
00464 }
00465
00466 gsg->pop_display_region(old_dr);
00467 }
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 void GraphicsEngine::
00479 cull_bin_draw(const GraphicsEngine::Windows &wlist) {
00480 Windows::const_iterator wi;
00481 for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
00482 GraphicsWindow *win = (*wi);
00483 if (win->is_active()) {
00484
00485 if (win->begin_frame()) {
00486 win->clear();
00487
00488 int num_display_regions = win->get_num_display_regions();
00489 for (int i = 0; i < num_display_regions; i++) {
00490 DisplayRegion *dr = win->get_display_region(i);
00491 cull_bin_draw(win->get_gsg(), dr);
00492 }
00493
00494 win->end_frame();
00495 }
00496 }
00497 }
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507 void GraphicsEngine::
00508 cull_bin_draw(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
00509 nassertv(gsg != (GraphicsStateGuardian *)NULL);
00510
00511 PT(CullResult) cull_result = dr->_cull_result;
00512 if (cull_result != (CullResult *)NULL) {
00513 cull_result = cull_result->make_next();
00514 } else {
00515 cull_result = new CullResult(gsg);
00516 }
00517
00518 PT(SceneSetup) scene_setup = setup_scene(dr->get_camera(), gsg);
00519 if (scene_setup != (SceneSetup *)NULL) {
00520 BinCullHandler cull_handler(cull_result);
00521 do_cull(&cull_handler, scene_setup, gsg);
00522
00523 cull_result->finish_cull();
00524
00525
00526 dr->_cull_result = cull_result;
00527
00528
00529
00530 do_draw(cull_result, scene_setup, gsg, dr);
00531 }
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541 void GraphicsEngine::
00542 process_events(const GraphicsEngine::Windows &wlist) {
00543 Windows::const_iterator wi;
00544 for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
00545 GraphicsWindow *win = (*wi);
00546 win->process_events();
00547 }
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557 void GraphicsEngine::
00558 flip_windows(const GraphicsEngine::Windows &wlist) {
00559 Windows::const_iterator wi;
00560 for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
00561 GraphicsWindow *win = (*wi);
00562 win->begin_flip();
00563 }
00564 for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
00565 GraphicsWindow *win = (*wi);
00566 win->end_flip();
00567 }
00568 }
00569
00570
00571
00572
00573
00574
00575
00576 void GraphicsEngine::
00577 do_sync_frame() {
00578 nassertv(_flip_state == FS_draw);
00579
00580
00581
00582 Threads::const_iterator ti;
00583 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00584 RenderThread *thread = (*ti).second;
00585 thread->_cv_mutex.lock();
00586 thread->_cv_mutex.release();
00587 }
00588
00589 _flip_state = FS_sync;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598 void GraphicsEngine::
00599 do_flip_frame() {
00600 nassertv(_flip_state == FS_draw || _flip_state == FS_sync);
00601
00602
00603
00604 Threads::const_iterator ti;
00605 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00606 RenderThread *thread = (*ti).second;
00607 thread->_cv_mutex.lock();
00608 }
00609
00610
00611 _app.do_flip(this);
00612 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00613 RenderThread *thread = (*ti).second;
00614 if (thread->_thread_state == TS_wait) {
00615 thread->_thread_state = TS_do_flip;
00616 thread->_cv.signal();
00617 }
00618 thread->_cv_mutex.release();
00619 }
00620
00621 _flip_state = FS_flip;
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 PT(SceneSetup) GraphicsEngine::
00633 setup_scene(const NodePath &camera, GraphicsStateGuardian *gsg) {
00634 if (camera.is_empty()) {
00635
00636 return NULL;
00637 }
00638
00639 Camera *camera_node;
00640 DCAST_INTO_R(camera_node, camera.node(), NULL);
00641
00642 if (!camera_node->is_active()) {
00643
00644 return NULL;
00645 }
00646
00647 Lens *lens = camera_node->get_lens();
00648 if (lens == (Lens *)NULL) {
00649
00650 return NULL;
00651 }
00652
00653 NodePath scene_root = camera_node->get_scene();
00654 if (scene_root.is_empty()) {
00655
00656 return NULL;
00657 }
00658
00659 PT(SceneSetup) scene_setup = new SceneSetup;
00660
00661
00662
00663
00664
00665 CPT(TransformState) camera_transform = camera.get_transform(scene_root);
00666 CPT(TransformState) world_transform = scene_root.get_transform(camera);
00667
00668
00669
00670
00671 CPT(TransformState) cs_transform = TransformState::make_identity();
00672 CoordinateSystem external_cs = gsg->get_coordinate_system();
00673 CoordinateSystem internal_cs = gsg->get_internal_coordinate_system();
00674 if (internal_cs != CS_default && internal_cs != external_cs) {
00675 cs_transform =
00676 TransformState::make_mat(LMatrix4f::convert_mat(external_cs, internal_cs));
00677 }
00678
00679 scene_setup->set_scene_root(scene_root);
00680 scene_setup->set_camera_path(camera);
00681 scene_setup->set_camera_node(camera_node);
00682 scene_setup->set_lens(lens);
00683 scene_setup->set_camera_transform(camera_transform);
00684 scene_setup->set_world_transform(world_transform);
00685 scene_setup->set_cs_transform(cs_transform);
00686
00687 return scene_setup;
00688 }
00689
00690
00691
00692
00693
00694
00695 void GraphicsEngine::
00696 do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
00697 GraphicsStateGuardian *gsg) {
00698
00699 PStatTimer timer(_cull_pcollector);
00700
00701 CullTraverser trav;
00702 trav.set_cull_handler(cull_handler);
00703 trav.set_depth_offset_decals(gsg->depth_offset_decals());
00704 trav.set_scene(scene_setup);
00705 trav.set_camera_mask(scene_setup->get_camera_node()->get_camera_mask());
00706
00707 if (view_frustum_cull) {
00708
00709
00710
00711
00712
00713 PT(BoundingVolume) bv = scene_setup->get_lens()->make_bounds();
00714
00715 if (bv != (BoundingVolume *)NULL &&
00716 bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
00717
00718 PT(GeometricBoundingVolume) local_frustum;
00719 local_frustum = DCAST(GeometricBoundingVolume, bv->make_copy());
00720 local_frustum->xform(scene_setup->get_camera_transform()->get_mat());
00721
00722 trav.set_view_frustum(local_frustum);
00723 }
00724 }
00725
00726 trav.traverse(scene_setup->get_scene_root());
00727 }
00728
00729
00730
00731
00732
00733
00734 void GraphicsEngine::
00735 do_draw(CullResult *cull_result, SceneSetup *scene_setup,
00736 GraphicsStateGuardian *gsg, DisplayRegion *dr) {
00737
00738 PStatTimer timer(_draw_pcollector);
00739
00740 if (setup_gsg(gsg, scene_setup)) {
00741 DisplayRegionStack old_dr = gsg->push_display_region(dr);
00742 gsg->prepare_display_region();
00743 if (dr->is_any_clear_active()) {
00744 gsg->clear(dr);
00745 }
00746 if (gsg->begin_scene()) {
00747 cull_result->draw();
00748 gsg->end_scene();
00749 }
00750 gsg->pop_display_region(old_dr);
00751 }
00752 }
00753
00754
00755
00756
00757
00758
00759
00760
00761 bool GraphicsEngine::
00762 setup_gsg(GraphicsStateGuardian *gsg, SceneSetup *scene_setup) {
00763 if (scene_setup == (SceneSetup *)NULL) {
00764
00765 return false;
00766 }
00767
00768 const Lens *lens = scene_setup->get_lens();
00769 if (lens == (const Lens *)NULL) {
00770
00771 return false;
00772 }
00773
00774 if (!gsg->set_lens(lens)) {
00775
00776 display_cat.error()
00777 << gsg->get_type() << " cannot render with " << lens->get_type()
00778 << "\n";
00779 return false;
00780 }
00781
00782 gsg->set_scene(scene_setup);
00783
00784 return true;
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 void GraphicsEngine::
00796 do_remove_window(GraphicsWindow *window) {
00797 PT(GraphicsPipe) pipe = window->get_pipe();
00798 window->_pipe = (GraphicsPipe *)NULL;
00799
00800
00801 _app.remove_window(window);
00802 Threads::const_iterator ti;
00803 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00804 RenderThread *thread = (*ti).second;
00805 thread->remove_window(window);
00806 }
00807
00808
00809
00810 _app.do_pending(this);
00811 }
00812
00813
00814
00815
00816
00817
00818
00819 void GraphicsEngine::
00820 terminate_threads() {
00821 MutexHolder holder(_lock);
00822
00823
00824
00825 Threads::const_iterator ti;
00826 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00827 RenderThread *thread = (*ti).second;
00828 thread->_cv_mutex.lock();
00829 }
00830
00831
00832 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00833 RenderThread *thread = (*ti).second;
00834 if (thread->_thread_state == TS_wait) {
00835 thread->_thread_state = TS_do_release;
00836 thread->_cv.signal();
00837 }
00838 thread->_cv_mutex.release();
00839 }
00840
00841
00842 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00843 RenderThread *thread = (*ti).second;
00844 thread->_cv_mutex.lock();
00845 }
00846
00847
00848 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00849 RenderThread *thread = (*ti).second;
00850 MutexHolder cv_holder(thread->_cv_mutex);
00851 thread->_thread_state = TS_terminate;
00852 thread->_cv.signal();
00853 thread->_cv_mutex.release();
00854 }
00855
00856
00857 for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
00858 RenderThread *thread = (*ti).second;
00859 thread->join();
00860 }
00861
00862 _threads.clear();
00863 }
00864
00865
00866
00867
00868
00869
00870
00871
00872 GraphicsEngine::WindowRenderer *GraphicsEngine::
00873 get_window_renderer(const string &name) {
00874 if (name.empty()) {
00875 return &_app;
00876 }
00877
00878 MutexHolder holder(_lock);
00879 Threads::iterator ti = _threads.find(name);
00880 if (ti != _threads.end()) {
00881 return (*ti).second.p();
00882 }
00883
00884 PT(RenderThread) thread = new RenderThread(name, this);
00885 thread->start(TP_normal, true, true);
00886 _threads[name] = thread;
00887
00888 return thread.p();
00889 }
00890
00891
00892
00893
00894
00895
00896
00897 void GraphicsEngine::WindowRenderer::
00898 add_gsg(GraphicsStateGuardian *gsg) {
00899 MutexHolder holder(_wl_lock);
00900 _gsgs.insert(gsg);
00901 }
00902
00903
00904
00905
00906
00907
00908
00909 void GraphicsEngine::WindowRenderer::
00910 add_window(Windows &wlist, GraphicsWindow *window) {
00911 MutexHolder holder(_wl_lock);
00912 wlist.insert(window);
00913 }
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 void GraphicsEngine::WindowRenderer::
00924 remove_window(GraphicsWindow *window) {
00925 MutexHolder holder(_wl_lock);
00926 PT(GraphicsWindow) ptwin = window;
00927
00928 _cull.erase(ptwin);
00929
00930 Windows::iterator wi;
00931
00932 wi = _cdraw.find(ptwin);
00933 if (wi != _cdraw.end()) {
00934
00935
00936
00937
00938
00939
00940 _pending_release.insert(ptwin);
00941 _cdraw.erase(wi);
00942 }
00943
00944 wi = _draw.find(ptwin);
00945 if (wi != _draw.end()) {
00946
00947
00948
00949
00950
00951
00952 _pending_release.insert(ptwin);
00953 _draw.erase(wi);
00954 }
00955
00956 wi = _window.find(ptwin);
00957 if (wi != _window.end()) {
00958
00959
00960
00961
00962
00963 WindowProperties close_properties;
00964 close_properties.set_open(false);
00965 ptwin->request_properties(close_properties);
00966
00967
00968
00969
00970 if (!ptwin->is_closed()) {
00971 _pending_close.insert(ptwin);
00972 }
00973
00974 _window.erase(wi);
00975 }
00976 }
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 void GraphicsEngine::WindowRenderer::
00987 do_frame(GraphicsEngine *engine) {
00988 MutexHolder holder(_wl_lock);
00989 engine->cull_bin_draw(_cull);
00990 engine->cull_and_draw_together(_cdraw);
00991 engine->process_events(_window);
00992
00993
00994
00995 if (any_done_gsgs()) {
00996 GSGs new_gsgs;
00997 GSGs::iterator gi;
00998 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
00999 GraphicsStateGuardian *gsg = (*gi);
01000 if (gsg->get_ref_count() == 1) {
01001
01002 GraphicsPipe *pipe = gsg->get_pipe();
01003 engine->close_gsg(pipe, gsg);
01004 } else {
01005
01006 new_gsgs.insert(gsg);
01007 }
01008 }
01009
01010 _gsgs.swap(new_gsgs);
01011 }
01012 }
01013
01014
01015
01016
01017
01018
01019
01020 void GraphicsEngine::WindowRenderer::
01021 do_flip(GraphicsEngine *engine) {
01022 MutexHolder holder(_wl_lock);
01023 engine->flip_windows(_cdraw);
01024 engine->flip_windows(_draw);
01025 }
01026
01027
01028
01029
01030
01031
01032
01033 void GraphicsEngine::WindowRenderer::
01034 do_release(GraphicsEngine *) {
01035 MutexHolder holder(_wl_lock);
01036 Windows::iterator wi;
01037 for (wi = _draw.begin(); wi != _draw.end(); ++wi) {
01038 GraphicsWindow *win = (*wi);
01039 win->release_gsg();
01040 }
01041 }
01042
01043
01044
01045
01046
01047
01048 void GraphicsEngine::WindowRenderer::
01049 do_close(GraphicsEngine *engine) {
01050 WindowProperties close_properties;
01051 close_properties.set_open(false);
01052
01053 MutexHolder holder(_wl_lock);
01054 Windows::iterator wi;
01055 for (wi = _window.begin(); wi != _window.end(); ++wi) {
01056 GraphicsWindow *win = (*wi);
01057 win->set_properties_now(close_properties);
01058 }
01059
01060
01061 GSGs new_gsgs;
01062 GSGs::iterator gi;
01063 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
01064 GraphicsStateGuardian *gsg = (*gi);
01065 if (gsg->get_ref_count() == 1) {
01066
01067 GraphicsPipe *pipe = gsg->get_pipe();
01068 engine->close_gsg(pipe, gsg);
01069 } else {
01070
01071 new_gsgs.insert(gsg);
01072 }
01073 }
01074
01075 _gsgs.swap(new_gsgs);
01076 }
01077
01078
01079
01080
01081
01082
01083
01084 void GraphicsEngine::WindowRenderer::
01085 do_pending(GraphicsEngine *engine) {
01086 MutexHolder holder(_wl_lock);
01087
01088 if (!_pending_release.empty()) {
01089
01090 Windows::iterator wi;
01091 for (wi = _pending_release.begin(); wi != _pending_release.end(); ++wi) {
01092 GraphicsWindow *win = (*wi);
01093 win->release_gsg();
01094 }
01095 _pending_release.clear();
01096 }
01097
01098 if (!_pending_close.empty()) {
01099 WindowProperties close_properties;
01100 close_properties.set_open(false);
01101
01102
01103
01104 Windows new_pending_close;
01105 Windows::iterator wi;
01106 for (wi = _pending_close.begin(); wi != _pending_close.end(); ++wi) {
01107 GraphicsWindow *win = (*wi);
01108 if (win->get_gsg() == (GraphicsStateGuardian *)NULL) {
01109 win->set_properties_now(close_properties);
01110 } else {
01111
01112
01113 new_pending_close.insert(win);
01114 }
01115 }
01116 _pending_close.swap(new_pending_close);
01117 }
01118 }
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128 bool GraphicsEngine::WindowRenderer::
01129 any_done_gsgs() const {
01130 GSGs::const_iterator gi;
01131 for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
01132 if ((*gi)->get_ref_count() == 1) {
01133 return true;
01134 }
01135 }
01136
01137 return false;
01138 }
01139
01140
01141
01142
01143
01144
01145 GraphicsEngine::RenderThread::
01146 RenderThread(const string &name, GraphicsEngine *engine) :
01147 Thread(name),
01148 _engine(engine),
01149 _cv(_cv_mutex)
01150 {
01151 _thread_state = TS_wait;
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161 void GraphicsEngine::RenderThread::
01162 thread_main() {
01163 MutexHolder holder(_cv_mutex);
01164 while (true) {
01165 _cv.wait();
01166 switch (_thread_state) {
01167 case TS_wait:
01168 break;
01169
01170 case TS_do_frame:
01171 do_pending(_engine);
01172 do_frame(_engine);
01173 _thread_state = TS_wait;
01174 break;
01175
01176 case TS_do_flip:
01177 do_flip(_engine);
01178 _thread_state = TS_wait;
01179 break;
01180
01181 case TS_do_release:
01182 do_pending(_engine);
01183 do_release(_engine);
01184 _thread_state = TS_wait;
01185 break;
01186
01187 case TS_terminate:
01188 do_pending(_engine);
01189 do_close(_engine);
01190 return;
01191 }
01192 }
01193 }