ba375e10318195cc770bca37552288d64bb6d816
[chaz/yoink] / src / Moof / Video.cc
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 *******************************************************************************/
28
29 #include "Dispatch.hh"
30 #include "Engine.hh"
31 #include "Error.hh"
32 #include "Image.hh"
33 #include "Log.hh"
34 #include "Settings.hh"
35 #include "Video.hh"
36
37
38 namespace Mf {
39
40
41 Video::Video()
42 {
43 init(mAttribs);
44 }
45
46 Video::Video(const Attributes& attribs)
47 {
48 init(attribs);
49 }
50
51 Video::Video(const std::string& caption, const std::string& icon)
52 {
53 if (mAttribs.caption == "Untitled")
54 {
55 mAttribs.caption = caption;
56 }
57 if (mAttribs.icon == "")
58 {
59 mAttribs.icon = icon;
60 }
61
62 init(mAttribs);
63 }
64
65 void Video::init(const Attributes& attribs)
66 {
67 mContext = 0;
68 mFlags = 0;
69 mAttribs = attribs;
70
71 setFull(attribs.fullscreen);
72 setResizable(attribs.resizable);
73 setOpenGLAttributes();
74 setCaption(attribs.caption);
75 setIcon();
76 setCursorVisible(attribs.cursorVisible);
77 setCursorGrab(attribs.cursorGrab);
78 setVideoMode(attribs.mode);
79 }
80
81 void Video::recreateContext()
82 {
83 SDL_FreeSurface(mContext);
84 mContext = 0;
85 setVideoMode(mAttribs.mode);
86 }
87
88 void Video::setOpenGLAttributes()
89 {
90 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, mAttribs.colorBuffer[0]);
91 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, mAttribs.colorBuffer[1]);
92 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, mAttribs.colorBuffer[2]);
93 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, mAttribs.colorBuffer[3]);
94 SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, mAttribs.frameBuffer);
95 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, mAttribs.doubleBuffer);
96 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, mAttribs.depthBuffer);
97 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, mAttribs.stencilBuffer);
98 SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, mAttribs.accumBuffer[0]);
99 SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, mAttribs.accumBuffer[1]);
100 SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, mAttribs.accumBuffer[2]);
101 SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, mAttribs.accumBuffer[3]);
102 SDL_GL_SetAttribute(SDL_GL_STEREO, mAttribs.stereo);
103 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, mAttribs.multisampleBuffers);
104 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mAttribs.multisampleSamples);
105 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, mAttribs.swapControl);
106 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, mAttribs.hardwareonly);
107 }
108
109
110 Video::~Video()
111 {
112 SDL_FreeSurface(mContext);
113 }
114
115
116 void Video::setVideoMode(const long mode[3])
117 {
118 if (mode != mAttribs.mode || !mContext)
119 {
120 if (mContext) SDL_FreeSurface(mContext);
121
122 mContext = SDL_SetVideoMode(mode[0], mode[1], mode[2],
123 SDL_OPENGL | mFlags);
124
125 if (mContext)
126 {
127 mAttribs.mode[0] = mode[0];
128 mAttribs.mode[1] = mode[1];
129 mAttribs.mode[2] = mode[2];
130
131 #if defined(_WIN32) || defined(__WIN32__)
132 // on win32, creating a new context via SDL_SetVideoMode will wipe
133 // out the GL state, so we gotta notify everyone to reload their
134 // state after the change
135 Engine::getInstance().dispatch("video.newcontext");
136
137 logInfo("video context recreated");
138 #endif
139 }
140 else throw Error(Error::SDL_VIDEOMODE);
141 }
142 }
143
144 Video::Attributes Video::getAttributes() const
145 {
146 return mAttribs;
147 }
148
149
150 void Video::resize(int width, int height)
151 {
152 long mode[] = {width, height, mAttribs.mode[2]};
153 setVideoMode(mode);
154 }
155
156 bool Video::iconify()
157 {
158 return SDL_WM_IconifyWindow();
159 }
160
161
162 void Video::setCaption(const std::string& caption)
163 {
164 mAttribs.caption = caption;
165 SDL_WM_SetCaption(caption.c_str(), 0);
166 }
167
168 void Video::setIcon()
169 {
170 if (mAttribs.icon != "")
171 {
172 Image icon(mAttribs.icon);
173 icon.setAsIcon();
174 }
175 }
176
177 std::string Video::getCaption() const
178 {
179 return mAttribs.caption;
180 }
181
182 const std::string& Video::getIcon() const
183 {
184 return mAttribs.icon;
185 }
186
187
188 void Video::setFull(bool full)
189 {
190 if (full != isFull() || !mContext)
191 {
192 if (mContext)
193 {
194 mFlags ^= SDL_FULLSCREEN;
195
196 #if defined(linux) || defined(__linux) || defined(__linux__)
197 if (SDL_WM_ToggleFullScreen(mContext) == 0)
198 #endif
199 recreateContext();
200 }
201 else
202 {
203 if (full) mFlags |= SDL_FULLSCREEN;
204 else mFlags &= ~SDL_FULLSCREEN;
205 }
206 }
207 }
208
209 void Video::toggleFull()
210 {
211 setFull(!isFull());
212 }
213
214 bool Video::isFull() const
215 {
216 return mFlags & SDL_FULLSCREEN;
217 }
218
219
220 void Video::setCursorVisible(bool hasCursor)
221 {
222 SDL_ShowCursor(hasCursor? SDL_ENABLE : SDL_DISABLE);
223 }
224
225 void Video::toggleCursorVisible()
226 {
227 setCursorVisible(!isCursorVisible());
228 }
229
230 bool Video::isCursorVisible() const
231 {
232 return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE);
233 }
234
235
236 void Video::setResizable(bool resizable)
237 {
238 if (resizable != isResizable() || !mContext)
239 {
240 if (mContext)
241 {
242 mFlags ^= SDL_RESIZABLE;
243 recreateContext();
244 }
245 else
246 {
247 if (resizable) mFlags |= SDL_RESIZABLE;
248 else mFlags &= ~SDL_RESIZABLE;
249 }
250 }
251 }
252
253 void Video::toggleResizable()
254 {
255 setResizable(!isResizable());
256 }
257
258 bool Video::isResizable() const
259 {
260 return mFlags & SDL_RESIZABLE;
261 }
262
263
264 bool Video::isCursorGrab() const
265 {
266 return (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON);
267 }
268
269 void Video::toggleCursorGrab()
270 {
271 setCursorGrab(!isCursorGrab());
272 }
273
274 void Video::setCursorGrab(bool cursorGrab)
275 {
276 SDL_WM_GrabInput(cursorGrab? SDL_GRAB_ON : SDL_GRAB_OFF);
277 }
278
279
280 void Video::swap()
281 {
282 SDL_GL_SwapBuffers();
283 }
284
285
286 int Video::getWidth() const
287 {
288 return mContext->w;
289 }
290
291 int Video::getHeight() const
292 {
293 return mContext->h;
294 }
295
296
297 Video::Attributes::Attributes()
298 {
299 // Set some sane GL and window defaults (see SDL_video.c:217)
300 colorBuffer[0] = 3;
301 colorBuffer[1] = 3;
302 colorBuffer[2] = 2;
303 colorBuffer[3] = 0;
304 frameBuffer = 0;
305 doubleBuffer = true;
306 depthBuffer = 16;
307 stencilBuffer = 0;
308 accumBuffer[0] = 0;
309 accumBuffer[1] = 0;
310 accumBuffer[2] = 0;
311 accumBuffer[3] = 0;
312 stereo = false;
313 multisampleBuffers = 0;
314 multisampleSamples = 0;
315 swapControl = false;
316 hardwareonly = false;
317 mode[0] = 640;
318 mode[1] = 480;
319 mode[2] = 0;
320 fullscreen = false;
321 resizable = false;
322 cursorVisible = true;
323 cursorGrab = false;
324
325 Settings& settings = Settings::getInstance();
326
327 std::vector<long> colors;
328 settings.get("colorbuffers", colors);
329 if (colors.size() > 0) colorBuffer[0] = colors[0];
330 if (colors.size() > 1) colorBuffer[1] = colors[1];
331 if (colors.size() > 2) colorBuffer[2] = colors[2];
332 if (colors.size() > 3) colorBuffer[3] = colors[3];
333
334 settings.get("framebuffer", frameBuffer);
335 settings.get("doublebuffer", doubleBuffer);
336 settings.get("depthbuffer", depthBuffer);
337 settings.get("stencilbuffer", stencilBuffer);
338
339 std::vector<long> accum;
340 settings.get("accumbuffers", accum);
341 if (accum.size() > 0) accumBuffer[0] = accum[0];
342 if (accum.size() > 1) accumBuffer[1] = accum[1];
343 if (accum.size() > 2) accumBuffer[2] = accum[2];
344 if (accum.size() > 3) accumBuffer[3] = accum[3];
345
346 settings.get("stereo", stereo);
347 settings.get("multiesamplebuffers", multisampleBuffers);
348 settings.get("multiesamplesamples", multisampleSamples);
349 settings.get("swapcontrol", swapControl);
350 settings.get("hardwareonly", hardwareonly);
351
352 if (!settings.get("caption", caption))
353 {
354 caption = "Untitled";
355 }
356 settings.get("icon", icon);
357
358 settings.get("fullscreen", fullscreen);
359 settings.get("resizable", resizable);
360 settings.get("showcursor", cursorVisible);
361 settings.get("grab", cursorGrab);
362
363 std::vector<long> dimensions;
364 settings.get("videomode", dimensions);
365 if (dimensions.size() > 1)
366 {
367 mode[0] = dimensions[0];
368 mode[1] = dimensions[1];
369 }
370 else if (fullscreen)
371 {
372 SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
373
374 if (modes == (SDL_Rect**)0)
375 {
376 Mf::logError("no native video mode");
377 }
378 else if (modes == (SDL_Rect**)-1)
379 {
380 Mf::logWarning("any resolution allowed; choosing default 800x600");
381 mode[0] = 800;
382 mode[1] = 600;
383 }
384 else
385 {
386 while (*(modes + 1)) ++modes; // skip to the last
387
388 mode[0] = (*modes)->w;
389 mode[1] = (*modes)->h;
390 Mf::logInfo << "choosing native resolution "
391 << mode[0] << "x" << mode[1] << std::endl;
392 }
393 }
394 if (dimensions.size() > 2) mode[2] = dimensions[2];
395 }
396
397
398 } // namespace Mf
399
400 /** vim: set ts=4 sw=4 tw=80: *************************************************/
401
This page took 0.046862 seconds and 3 git commands to generate.