#include <SDL_opengl.h>
#include <SDL_image.h>
using namespace hrk;
using namespace std;
namespace
{
enum {
Current_depth_bpp = 0,
};
SDL_Surface* screen_ = NULL;
double x_magnify_ = 1.0;
double y_magnify_ = 1.0;
void tear_down_screen(void)
{
if (screen_) {
SDL_QuitSubSystem(SDL_INIT_VIDEO);
screen_ = NULL;
}
}
}
{
string error_message_;
int video_bpp_;
Uint32 video_flags_;
string caption_text_;
string icon_image_file_;
SDL_Surface* icon_image_;
pImpl(void)
: error_message_("no error."),
video_bpp_(Current_depth_bpp), video_flags_(0x0),
icon_image_(NULL)
{
atexit(tear_down_screen);
}
~pImpl(void)
{
delete icon_image_;
}
static pImpl* singleton(void)
{
static pImpl singleton_object;
return &singleton_object;
}
void set_fullscreen(bool on)
{
if (on == ((video_flags_ & SDL_FULLSCREEN) ? true : false)) {
return;
}
Uint32 previous_flags = video_flags_;
video_flags_ ^= SDL_FULLSCREEN;
if (!screen_) {
return;
}
if (!show(Keep_size)) {
video_flags_ = previous_flags;
show(Keep_size);
}
}
void set_caption(void)
{
SDL_WM_SetCaption(caption_text_.c_str(), caption_text_.c_str());
}
bool show(
const SizeF& size)
{
if (!is_initialized()) {
initialize();
}
initialize_opengl();
if (!icon_image_file_.empty()) {
icon_image_ = IMG_Load(icon_image_file_.c_str());
SDL_WM_SetIcon(icon_image_, NULL);
}
screen_ = SDL_SetVideoMode(static_cast<int>(size.
width()),
static_cast<int>(size.
height()),
video_bpp_, video_flags_ | SDL_OPENGL);
if (!screen_) {
error_message_ = SDL_GetError();
return false;
}
set_caption();
if ((size.width() > 0) && (size.height() > 0)) {
window_size_ = size;
}
return true;
}
void hide(void)
{
terminate();
screen_ = NULL;
}
void initialize_opengl(void)
{
int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
int rgb_size[3];
switch (bpp) {
case 8:
rgb_size[0] = 3;
rgb_size[1] = 3;
rgb_size[2] = 2;
break;
case 15:
case 16:
rgb_size[0] = 5;
rgb_size[1] = 5;
rgb_size[2] = 5;
break;
default:
rgb_size[0] = 8;
rgb_size[1] = 8;
rgb_size[2] = 8;
break;
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, rgb_size[0]);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, rgb_size[1]);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, rgb_size[2]);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
}
};
Main_window::Main_window(void) : pimpl(pImpl::singleton())
{
}
Main_window::~Main_window(void)
{
}
const char* Main_window::what(void) const
{
return pimpl->error_message_.c_str();
}
{
pimpl->icon_image_file_ = image_file;
}
void Main_window::set_caption_text(const std::string& text)
{
pimpl->caption_text_ = text;
pimpl->set_caption();
}
void Main_window::set_fullscreen(bool on)
{
pimpl->set_fullscreen(on);
}
bool Main_window::show(
const SizeF& size)
{
return pimpl->show(size);
}
SizeF Main_window::size(
void)
const
{
return window_size_;
}
void Main_window::hide(void)
{
pimpl->hide();
}
bool Main_window::is_visible(void) const
{
return screen_ ? true : false;
}
void Main_window::clear(void)
{
if (!screen_) {
return;
}
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Main_window::update(void)
{
if (!screen_) {
return;
}
SDL_GL_SwapBuffers();
}
void Main_window::set_window_rect(
const RectF& offset_magnify)
{
screen_offset_ = offset_magnify.
point();
x_magnify_ = offset_magnify.
width();
y_magnify_ = offset_magnify.
height();
}
{
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glViewport(static_cast<GLsizei>(screen_offset_.x()),
static_cast<GLsizei>(screen_offset_.y()),
static_cast<GLsizei>(window_size_.width() * x_magnify_),
static_cast<GLsizei>(window_size_.height() * y_magnify_));
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, window_size_.width() - 1.0,
window_size_.height() - 1.0, 0.0, +1.0, -1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
}
{
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
{
if (use_depth_test) {
glEnable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GEQUAL, static_cast<GLclampf>(0.1));
} else {
glDisable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
}
}
{
GLdouble clip_left[] = { 1.0, 0.0, 0.0, 0.0 };
clip_left[3] = -rect.
x();
GLdouble clip_right[] = { -1.0, 0.0, 0.0, 0.0 };
clip_right[3] = rect.
x() + rect.
width();
GLdouble clip_top[] = { 0.0, 1.0, 0.0, 0.0 };
GLdouble clip_bottom[] = { 0.0, -1.0, 0.0, 0.0 };
clip_bottom[3] = rect.
y() + rect.
height();
glClipPlane(GL_CLIP_PLANE0, clip_left);
glClipPlane(GL_CLIP_PLANE1, clip_right);
glClipPlane(GL_CLIP_PLANE2, clip_top);
glClipPlane(GL_CLIP_PLANE3, clip_bottom);
glEnable(GL_CLIP_PLANE0);
glEnable(GL_CLIP_PLANE1);
glEnable(GL_CLIP_PLANE2);
glEnable(GL_CLIP_PLANE3);
}
{
glDisable(GL_CLIP_PLANE0);
glDisable(GL_CLIP_PLANE1);
glDisable(GL_CLIP_PLANE2);
glDisable(GL_CLIP_PLANE3);
}