]> git.mxchange.org Git - flightgear.git/blob - src/Main/WindowBuilder.cxx
NavDisplay: fix update lag when switching range or centre.
[flightgear.git] / src / Main / WindowBuilder.cxx
1 // Copyright (C) 2008  Tim Moore
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License as
5 // published by the Free Software Foundation; either version 2 of the
6 // License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16
17 #include "WindowBuilder.hxx"
18
19 #include "WindowSystemAdapter.hxx"
20 #include "fg_props.hxx"
21
22 #include <sstream>
23
24 using namespace std;
25 using namespace osg;
26
27 namespace flightgear
28 {
29 string makeName(const string& prefix, int num)
30 {
31     stringstream stream;
32     stream << prefix << num;
33     return stream.str();
34 }
35
36 ref_ptr<WindowBuilder> WindowBuilder::windowBuilder;
37
38 const string WindowBuilder::defaultWindowName("FlightGear");
39
40 void WindowBuilder::initWindowBuilder(bool stencil)
41 {
42     windowBuilder = new WindowBuilder(stencil);
43 }
44
45 WindowBuilder::WindowBuilder(bool stencil) : defaultCounter(0)
46 {
47     defaultTraits = makeDefaultTraits(stencil);
48 }
49
50 GraphicsContext::Traits*
51 WindowBuilder::makeDefaultTraits(bool stencil)
52 {
53     GraphicsContext::WindowingSystemInterface* wsi
54         = osg::GraphicsContext::getWindowingSystemInterface();
55     GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits;
56
57     traits->readDISPLAY();
58     if (traits->displayNum < 0)
59         traits->displayNum = 0;
60     if (traits->screenNum < 0)
61         traits->screenNum = 0;
62
63     int bpp = fgGetInt("/sim/rendering/bits-per-pixel");
64     bool alpha = fgGetBool("/sim/rendering/clouds3d-enable");
65     int cbits = (bpp <= 16) ?  5 :  8;
66     int zbits = (bpp <= 16) ? 16 : 24;
67     traits->red = traits->green = traits->blue = cbits;
68     traits->depth = zbits;
69     if (alpha)
70         traits->alpha = 8;
71
72     if (stencil)
73         traits->stencil = 8;
74
75     unsigned screenwidth = 0;
76     unsigned screenheight = 0;
77     wsi->getScreenResolution(*traits, screenwidth, screenheight);
78
79     traits->doubleBuffer = true;
80     traits->mipMapGeneration = true;
81     traits->windowName = "FlightGear";
82     // XXX should check per window too.
83     traits->sampleBuffers = fgGetBool("/sim/rendering/multi-sample-buffers", traits->sampleBuffers);
84     traits->samples = fgGetInt("/sim/rendering/multi-samples", traits->samples);
85     traits->vsync = fgGetBool("/sim/rendering/vsync-enable", traits->vsync);
86     traits->windowDecoration = !fgGetBool("/sim/startup/fullscreen");
87
88     if (!traits->windowDecoration) {
89         // fullscreen
90         traits->supportsResize = false;
91         traits->width = screenwidth;
92         traits->height = screenheight;
93         SG_LOG(SG_VIEW,SG_DEBUG,"Using full screen size for window: " << screenwidth << " x " << screenheight);
94     } else {
95         // window
96         int w = fgGetInt("/sim/startup/xsize");
97         int h = fgGetInt("/sim/startup/ysize");
98         traits->supportsResize = true;
99         traits->width = w;
100         traits->height = h;
101         if ((w>0)&&(h>0))
102         {
103             traits->x = ((unsigned)w>screenwidth) ? 0 : (screenwidth-w)/3;
104             traits->y = ((unsigned)h>screenheight) ? 0 : (screenheight-h)/3;
105         }
106         SG_LOG(SG_VIEW,SG_DEBUG,"Using initial window size: " << w << " x " << h);
107     }
108     return traits;
109 }
110 }
111
112 namespace
113 {
114 // Helper functions that set a value based on a property if it exists,
115 // returning 1 if the value was set.
116
117 inline int setFromProperty(string& place, const SGPropertyNode* node,
118                             const char* name)
119 {
120     const SGPropertyNode* valNode = node->getNode(name);
121     if (valNode) {
122         place = valNode->getStringValue();
123         return 1;
124     }
125     return 0;
126 }
127
128 inline int setFromProperty(int& place, const SGPropertyNode* node,
129                             const char* name)
130 {
131     const SGPropertyNode* valNode = node->getNode(name);
132     if (valNode) {
133         place = valNode->getIntValue();
134         return 1;
135     }
136     return 0;
137 }
138
139 inline int setFromProperty(bool& place, const SGPropertyNode* node,
140                             const char* name)
141 {
142     const SGPropertyNode* valNode = node->getNode(name);
143     if (valNode) {
144         place = valNode->getBoolValue();
145         return 1;
146     }
147     return 0;
148 }
149 }
150
151 namespace flightgear
152 {
153 GraphicsWindow* WindowBuilder::buildWindow(const SGPropertyNode* winNode)
154 {
155     GraphicsContext::WindowingSystemInterface* wsi
156         = osg::GraphicsContext::getWindowingSystemInterface();
157     WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
158     string windowName;
159     if (winNode->hasChild("window-name"))
160         windowName = winNode->getStringValue("window-name");
161     else if (winNode->hasChild("name"))
162         windowName = winNode->getStringValue("name");
163     GraphicsWindow* result = 0;
164     if (!windowName.empty()) {
165         result = wsa->findWindow(windowName);
166         if (result)
167             return result;
168     }
169     GraphicsContext::Traits* traits
170         = new GraphicsContext::Traits(*defaultTraits);
171     int traitsSet = setFromProperty(traits->hostName, winNode, "host-name");
172     traitsSet |= setFromProperty(traits->displayNum, winNode, "display");
173     traitsSet |= setFromProperty(traits->screenNum, winNode, "screen");
174
175     const SGPropertyNode* fullscreenNode = winNode->getNode("fullscreen");
176
177     if (fullscreenNode && fullscreenNode->getBoolValue()) {
178         // fullscreen mode
179         unsigned width = 0;
180         unsigned height = 0;
181         wsi->getScreenResolution(*traits, width, height);
182         traits->windowDecoration = false;
183         traits->width = width;
184         traits->height = height;
185         traits->supportsResize = false;
186         traits->x = 0;
187         traits->y = 0;
188         traitsSet = 1;
189     } else {
190         int resizable = 0;
191         if (fullscreenNode && !fullscreenNode->getBoolValue())
192         {
193             traits->windowDecoration = true;
194             resizable = 1;
195         }
196         resizable |= setFromProperty(traits->windowDecoration, winNode,
197                                      "decoration");
198         resizable |= setFromProperty(traits->width, winNode, "width");
199         resizable |= setFromProperty(traits->height, winNode, "height");
200         if (resizable) {
201             traits->supportsResize = true;
202             traitsSet = 1;
203         }
204         // Otherwise use default values.
205     }
206     traitsSet |= setFromProperty(traits->x, winNode, "x");
207     traitsSet |= setFromProperty(traits->y, winNode, "y");
208     if (!windowName.empty() && windowName != traits->windowName) {
209         traits->windowName = windowName;
210         traitsSet = 1;
211     } else if (traitsSet) {
212         traits->windowName = makeName("FlightGear", defaultCounter++);
213     }
214     bool drawGUI = false;
215     traitsSet |= setFromProperty(drawGUI, winNode, "gui");
216     if (traitsSet) {
217         GraphicsContext* gc = GraphicsContext::createGraphicsContext(traits);
218         if (gc) {
219             GraphicsWindow* window = WindowSystemAdapter::getWSA()
220                 ->registerWindow(gc, traits->windowName);
221             if (drawGUI)
222                 window->flags |= GraphicsWindow::GUI;
223             return window;
224         } else {
225             return 0;
226         }
227     } else {
228         // XXX What if the window has no traits, but does have a name?
229         // We should create a "default window" registered with that name.
230         return getDefaultWindow();
231     }
232 }
233
234 GraphicsWindow* WindowBuilder::getDefaultWindow()
235 {
236     GraphicsWindow* defaultWindow
237         = WindowSystemAdapter::getWSA()->findWindow(defaultWindowName);
238     if (defaultWindow)
239         return defaultWindow;
240     GraphicsContext::Traits* traits
241         = new GraphicsContext::Traits(*defaultTraits);
242     traits->windowName = "FlightGear";
243     
244     GraphicsContext* gc = GraphicsContext::createGraphicsContext(traits);
245     if (gc) {
246         defaultWindow = WindowSystemAdapter::getWSA()
247             ->registerWindow(gc, defaultWindowName);
248         return defaultWindow;
249     } else {
250         SG_LOG(SG_VIEW, SG_ALERT, "getDefaultWindow: failed to create GraphicsContext");
251         return 0;
252     }
253 }
254 }