-/*******************************************************************************
-
- Copyright (c) 2009, Charles McGarvey
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*******************************************************************************/
-
-#include <stdexcept>
-
-#include <SDL/SDL_image.h>
-
-#include "Dispatcher.hh"
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include "Dispatch.hh"
+#include "Error.hh"
+#include "Image.hh"
#include "Log.hh"
-#include "Serializable.hh"
#include "Settings.hh"
#include "Video.hh"
Video::Video()
{
- init(attribs_);
+ init();
}
-Video::Video(const Attributes& attribs)
+Video::Video(const Attributes& attribs) :
+ mAttribs(attribs)
{
- init(attribs);
+ init();
}
Video::Video(const std::string& caption, const std::string& icon)
{
- if (attribs_.caption == "Untitled")
- {
- attribs_.caption = caption;
- }
- if (attribs_.icon == "")
- {
- attribs_.icon = icon;
- }
+ mAttribs.caption = caption;
+ mAttribs.icon = icon;
- init(attribs_);
+ init();
}
-void Video::init(const Attributes& attribs)
+void Video::init()
{
- context_ = 0;
- flags_ = 0;
- attribs_ = attribs;
+ Error error = Backend::getError();
+ if (error) error.raise();
+
+ mContext = 0;
+ mFlags = 0;
- setFull(attribs.fullscreen);
- setResizable(attribs.resizable);
+ setFull(mAttribs.fullscreen);
+ setResizable(mAttribs.resizable);
setOpenGLAttributes();
- setCaption(attribs.caption);
+ setCaption(mAttribs.caption);
setIcon();
- setCursorVisible(attribs.cursorVisible);
- setCursorGrab(attribs.cursorGrab);
- setVideoMode(attribs.mode);
+ setCursorVisible(mAttribs.cursorVisible);
+ setCursorGrab(mAttribs.cursorGrab);
+ setVideoMode(mAttribs.mode);
+
+ video = this;
}
void Video::recreateContext()
{
- SDL_FreeSurface(context_);
- context_ = 0;
- setVideoMode(attribs_.mode);
+ SDL_FreeSurface(mContext);
+ mContext = 0;
+ setVideoMode(mAttribs.mode);
}
void Video::setOpenGLAttributes()
{
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, attribs_.colorBuffer[0]);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, attribs_.colorBuffer[1]);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, attribs_.colorBuffer[2]);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, attribs_.colorBuffer[3]);
- SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, attribs_.frameBuffer);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, attribs_.doubleBuffer);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, attribs_.depthBuffer);
- SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, attribs_.stencilBuffer);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, attribs_.accumBuffer[0]);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, attribs_.accumBuffer[1]);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, attribs_.accumBuffer[2]);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, attribs_.accumBuffer[3]);
- SDL_GL_SetAttribute(SDL_GL_STEREO, attribs_.stereo);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, attribs_.multisampleBuffers);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, attribs_.multisampleSamples);
- SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, attribs_.swapControl);
- SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, attribs_.hardwareonly);
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE,
+ mAttribs.colorBuffer[0]);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,
+ mAttribs.colorBuffer[1]);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,
+ mAttribs.colorBuffer[2]);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,
+ mAttribs.colorBuffer[3]);
+ SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,
+ mAttribs.frameBuffer);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,
+ mAttribs.doubleBuffer);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,
+ mAttribs.depthBuffer);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,
+ mAttribs.stencilBuffer);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE,
+ mAttribs.accumBuffer[0]);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE,
+ mAttribs.accumBuffer[1]);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE,
+ mAttribs.accumBuffer[2]);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE,
+ mAttribs.accumBuffer[3]);
+ SDL_GL_SetAttribute(SDL_GL_STEREO,
+ mAttribs.stereo);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,
+ mAttribs.multisampleBuffers);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES,
+ mAttribs.multisampleSamples);
+ SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL,
+ mAttribs.swapControl);
+ SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,
+ mAttribs.hardwareOnly);
}
Video::~Video()
{
- SDL_FreeSurface(context_);
+ SDL_FreeSurface(mContext);
+
+ if (video == this) video = 0;
}
void Video::setVideoMode(const long mode[3])
{
- if (mode != attribs_.mode || !context_)
+ if (mode != mAttribs.mode || !mContext)
{
- if (context_) SDL_FreeSurface(context_);
+ if (mContext) SDL_FreeSurface(mContext);
- context_ = SDL_SetVideoMode(mode[0], mode[1], mode[2],
- SDL_OPENGL | flags_);
+ mContext = SDL_SetVideoMode(mode[0], mode[1], mode[2],
+ SDL_OPENGL | mFlags);
- if (context_)
+ if (mContext)
{
- attribs_.mode[0] = mode[0];
- attribs_.mode[1] = mode[1];
- attribs_.mode[2] = mode[2];
-
-#if defined(_WIN32) || defined (_WIN64) || defined(__WIN32__)
- // on win32, creating a new context via SDL_SetVideoMode will wipe
- // out the GL state, so we gotta notify everyone to reload their
- // state after the change
- Mf::dispatcher::dispatch("video.context_recreated");
+ mAttribs.mode[0] = mode[0];
+ mAttribs.mode[1] = mode[1];
+ mAttribs.mode[2] = mode[2];
+
+#if !defined(linux) && !defined(__linux) && !defined(__linux__)
logInfo("video context recreated");
+ core.dispatch("video.newcontext");
#endif
}
- else throw Exception(SDL_GetError());
+ else Error(Error::SDL_VIDEOMODE).raise();
}
}
Video::Attributes Video::getAttributes() const
{
- return attribs_;
+ return mAttribs;
}
void Video::resize(int width, int height)
{
- long mode[] = {width, height, attribs_.mode[2]};
+ long mode[] = {width, height, mAttribs.mode[2]};
setVideoMode(mode);
}
void Video::setCaption(const std::string& caption)
{
- attribs_.caption = caption;
+ mAttribs.caption = caption;
SDL_WM_SetCaption(caption.c_str(), 0);
}
void Video::setIcon()
{
- if (attribs_.icon != "")
+ if (mAttribs.icon != "")
{
- SDL_Surface* icon = IMG_Load(attribs_.icon.c_str());
- if (icon)
- {
- SDL_WM_SetIcon(icon, 0);
- SDL_FreeSurface(icon);
- }
+ Image icon(mAttribs.icon);
+ icon.setAsIcon();
}
}
std::string Video::getCaption() const
{
- return attribs_.caption;
+ return mAttribs.caption;
+}
+
+const std::string& Video::getIcon() const
+{
+ return mAttribs.icon;
}
void Video::setFull(bool full)
{
- if (full != isFull() || !context_)
+ if (full != isFull() || !mContext)
{
- if (context_)
+ if (mContext)
{
- flags_ ^= SDL_FULLSCREEN;
+ mFlags ^= SDL_FULLSCREEN;
#if defined(linux) || defined(__linux) || defined(__linux__)
- if (SDL_WM_ToggleFullScreen(context_) == 0)
+ if (SDL_WM_ToggleFullScreen(mContext) == 0)
#endif
recreateContext();
}
else
{
- if (full) flags_ |= SDL_FULLSCREEN;
- else flags_ &= ~SDL_FULLSCREEN;
+ if (full) mFlags |= SDL_FULLSCREEN;
+ else mFlags &= ~SDL_FULLSCREEN;
}
}
}
bool Video::isFull() const
{
- return flags_ & SDL_FULLSCREEN;
+ return mFlags & SDL_FULLSCREEN;
}
void Video::setResizable(bool resizable)
{
- if (resizable != isResizable() || !context_)
+ if (resizable != isResizable() || !mContext)
{
- if (context_)
+ if (mContext)
{
- flags_ ^= SDL_RESIZABLE;
+ mFlags ^= SDL_RESIZABLE;
recreateContext();
}
else
{
- if (resizable) flags_ |= SDL_RESIZABLE;
- else flags_ &= ~SDL_RESIZABLE;
+ if (resizable) mFlags |= SDL_RESIZABLE;
+ else mFlags &= ~SDL_RESIZABLE;
}
}
}
bool Video::isResizable() const
{
- return flags_ & SDL_RESIZABLE;
+ return mFlags & SDL_RESIZABLE;
}
}
-void Video::makeActive()
+void Video::swap()
{
- // NOP until the day SDL supports more than only one window.
- // Still waiting...
+ SDL_GL_SwapBuffers();
}
-void Video::swap()
+
+int Video::getWidth() const
{
- SDL_GL_SwapBuffers();
+ return mContext->w;
+}
+
+int Video::getHeight() const
+{
+ return mContext->h;
}
Video::Attributes::Attributes()
{
- // Set some sane GL and window defaults (see SDL_video.c:217)
+ // set some sane GL and window defaults (see SDL_video.c:217)
colorBuffer[0] = 3;
colorBuffer[1] = 3;
colorBuffer[2] = 2;
multisampleBuffers = 0;
multisampleSamples = 0;
swapControl = false;
- hardwareonly = false;
+ hardwareOnly = false;
mode[0] = 640;
mode[1] = 480;
mode[2] = 0;
cursorVisible = true;
cursorGrab = false;
- Settings& settings = Settings::getInstance();
-
- Serializable::Array colors;
- settings.get("video.colorbuffers", colors);
- if (colors.size() > 0) colors[0]->get(colorBuffer[0]);
- if (colors.size() > 1) colors[1]->get(colorBuffer[1]);
- if (colors.size() > 2) colors[2]->get(colorBuffer[2]);
- if (colors.size() > 3) colors[3]->get(colorBuffer[3]);
-
- settings.get("video.framebuffer", frameBuffer);
- settings.get("video.doublebuffer", doubleBuffer);
- settings.get("video.depthbuffer", depthBuffer);
- settings.get("video.stencilbuffer", stencilBuffer);
-
- Serializable::Array accum;
- settings.get("video.accumbuffers", accum);
- if (accum.size() > 0) accum[0]->get(accumBuffer[0]);
- if (accum.size() > 1) accum[1]->get(accumBuffer[1]);
- if (accum.size() > 2) accum[2]->get(accumBuffer[2]);
- if (accum.size() > 3) accum[3]->get(accumBuffer[3]);
-
- settings.get("video.stereo", stereo);
- settings.get("video.multiesamplebuffers", multisampleBuffers);
- settings.get("video.multiesamplesamples", multisampleSamples);
- settings.get("video.swapcontrol", swapControl);
- settings.get("video.hardwareonly", hardwareonly);
-
- if (!settings.get("video.caption", caption))
+ std::vector<long> colors;
+ settings.get("colorbuffers", colors);
+ if (colors.size() > 0) colorBuffer[0] = colors[0];
+ if (colors.size() > 1) colorBuffer[1] = colors[1];
+ if (colors.size() > 2) colorBuffer[2] = colors[2];
+ if (colors.size() > 3) colorBuffer[3] = colors[3];
+
+ settings.get("framebuffer", frameBuffer);
+ settings.get("doublebuffer", doubleBuffer);
+ settings.get("depthbuffer", depthBuffer);
+ settings.get("stencilbuffer", stencilBuffer);
+
+ std::vector<long> accum;
+ settings.get("accumbuffers", accum);
+ if (accum.size() > 0) accumBuffer[0] = accum[0];
+ if (accum.size() > 1) accumBuffer[1] = accum[1];
+ if (accum.size() > 2) accumBuffer[2] = accum[2];
+ if (accum.size() > 3) accumBuffer[3] = accum[3];
+
+ settings.get("stereo", stereo);
+ settings.get("multiesamplebuffers", multisampleBuffers);
+ settings.get("multiesamplesamples", multisampleSamples);
+ settings.get("swapcontrol", swapControl);
+ settings.get("hardwareonly", hardwareOnly);
+
+ if (!settings.get("caption", caption))
{
caption = "Untitled";
}
- settings.get("video.icon", icon);
-
- Serializable::Array dimensions;
- settings.get("video.mode", dimensions);
- if (dimensions.size() > 0) dimensions[0]->get(mode[0]);
- if (dimensions.size() > 1) dimensions[1]->get(mode[1]);
- if (dimensions.size() > 2) dimensions[2]->get(mode[2]);
-
- settings.get("video.fullscreen", fullscreen);
- settings.get("video.resizable", resizable);
- settings.get("video.showcursor", cursorVisible);
- settings.get("input.grab", cursorGrab);
+ settings.get("icon", icon);
+
+ settings.get("fullscreen", fullscreen);
+ settings.get("resizable", resizable);
+ settings.get("showcursor", cursorVisible);
+ settings.get("grab", cursorGrab);
+
+ std::vector<long> dimensions;
+ settings.get("videomode", dimensions);
+ if (dimensions.size() > 1)
+ {
+ mode[0] = dimensions[0];
+ mode[1] = dimensions[1];
+ }
+ else if (fullscreen && Backend::isInitialized())
+ {
+ SDL_Rect** modes = SDL_ListModes(NULL,
+ SDL_FULLSCREEN | SDL_HWSURFACE);
+
+ if (modes == (SDL_Rect**)0)
+ {
+ Mf::logError("no native video mode");
+ }
+ else if (modes == (SDL_Rect**)-1)
+ {
+ Mf::logWarning("any resolution allowed; "
+ "choosing default 800x600");
+ mode[0] = 800;
+ mode[1] = 600;
+ }
+ else
+ {
+ mode[0] = (*modes)->w;
+ mode[1] = (*modes)->h;
+ Mf::logInfo << "choosing native resolution "
+ << mode[0] << "x" << mode[1] << std::endl;
+ }
+ }
+ if (dimensions.size() > 2) mode[2] = dimensions[2];
}
-} // namespace Mf
+Video* video = 0; // most recently instantiated instance
-/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
+} // namespace Mf