/* client/video.cc This file is part of the Osirion project and is distributed under the terms and conditions of the GNU General Public License version 2 */ #include #include #include "client/video.h" #include "client/view.h" #include "render/render.h" #include "core/core.h" #include "filesystem/filesystem.h" #include "sys/sys.h" #include using namespace render; namespace client { namespace video { int width = 0; int height = 0; int width_prev = 0; int height_prev = 0; const int width_default = 1024; const int height_default = 768; float aspect = 1; //--- cvars ------------------------------------------------------- core::Cvar *r_width; core::Cvar *r_height; core::Cvar *r_fullscreen; void reset() { // recalculate the video aspect aspect = (float) width / (float) height; // settup our viewport. gl::viewport(0, 0, width, height ); // reset the view view::reset(); } bool init() { con_print << "Initializing video..." << std::endl; // initialize cvars r_width = core::Cvar::get("r_width", width_default, core::Cvar::Archive); r_height = core::Cvar::get("r_height", height_default, core::Cvar::Archive); r_fullscreen = core::Cvar::get("r_fullscreen", "0", core::Cvar::Archive); int bpp = 0; int flags = 0; if( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 ) { con_error << "SDL_InitSubSystem() failed: " << SDL_GetError() << std::endl; return false; } const SDL_VideoInfo* sdl_videoinfo = SDL_GetVideoInfo(); if( !sdl_videoinfo) { con_error << "SDL_GetVideoInfo() failed: " << SDL_GetError() << std::endl; return false; } width_prev = width; height_prev = height; width = (int) r_width->value(); height = (int) r_height->value(); bpp = sdl_videoinfo->vfmt->BitsPerPixel; SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 2); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); if (r_fullscreen->value()) flags = SDL_OPENGL | SDL_FULLSCREEN; else flags = SDL_OPENGL; if(!SDL_SetVideoMode(width, height, bpp, flags )) { con_warn << "Failed to set video mode " << width << "x" << height << "x" << bpp << "bpp" << std::endl; if (width_prev && height_prev) { width = width_prev; height = height_prev; if(!SDL_SetVideoMode(width, height, bpp, flags )) { con_error << "Failed to restore video mode " << width << "x" << height << "x" << bpp << "bpp" << std::endl; return false; } } else return false; } con_print << " video mode " << width << "x" << height << "x" << bpp << "bpp" << std::endl; aspect = (float) width / (float) height; (*r_width) = width; (*r_height) = height; std::string version(core::name()); version += ' '; version.append(core::version()); SDL_WM_SetCaption(version.c_str(), 0); render::init(); video::reset(); view::init(); return true; } void frame(float seconds) { // render a client frame view::frame(seconds); SDL_GL_SwapBuffers(); } void shutdown() { con_print << "Shutting down video..." << std::endl; view::shutdown(); render::shutdown(); width = 0; height = 0; SDL_QuitSubSystem(SDL_INIT_VIDEO); } void screenshot() { int number = 0; bool available = false; std::string shortname; std::string filename; // make sure the screenshots folder exists filename.assign(filesystem::writedir); filename.append("screenshots/"); sys::mkdir(filename); // find the first available screenshotxxx.tga do { std::stringstream nstr; nstr << number; shortname.assign(nstr.str()); while(shortname.size() < 3) shortname.insert(0, 1, '0'); shortname.insert(0, "screenshots/osirion"); shortname.append(".tga"); filename.assign(filesystem::writedir); filename.append(shortname); FILE *handle = fopen(filename.c_str(), "r"); if (handle) { fclose(handle); number++; } else { available = true; } } while (!available); std::ofstream ofs(filename.c_str()); if (!ofs.is_open()) { con_warn << "Could not write " << shortname << std::endl; return; } // TGA header // TODO: RL-encoding, image ID // note: see http://www.fileformat.info/format/tga/egff.htm unsigned char header[18]; memset(header, 0, sizeof(header)); // byte 0 - image ID field lenght = 0 (no image ID field present) // byte 1 - color map type = 0 (no palette present) // byte 2 - image type = 2 (truecolor without RLE) header[2] = 2; // byte 3-11 - palette data (not used) // byte 12+13 - image width header[12] = (video::width & 0xff); header[13] = ((video::width >> 8) & 0xff); // byte 14+15 - image height header[14] = (video::height & 0xff); header[15] = ((video::height >> 8) & 0xff); // byte 16 - image color depth = 24 (RGB) header[16] = 24; // byte 17 - image descriptor byte header[17] = 0; // allocate buffer to hold the RGB data unsigned char *rgb_data = (unsigned char *) malloc(video::width * video::height * 3); // read OpenGL pixels into the buffer //glReadBuffer(GL_FRONT); glReadPixels(0, 0, (GLsizei) video::width, (GLsizei) video::height, GL_RGB, GL_UNSIGNED_BYTE, (void *) rgb_data); // either OpenGL actually returns BGR, or TGA wants BGR for (size_t i = 0; i < (size_t) (video::width * video::height); i++) { unsigned char tmp = rgb_data[i*3]; rgb_data[i*3] = rgb_data[i*3+2]; rgb_data[i*3+2] = tmp; } ofs.write((char *)header, sizeof(header)); ofs.write((char *)rgb_data, video::width * video::height * 3 ); // free the buffer free(rgb_data); // close file ofs.close(); con_print << "Wrote " << shortname << std::endl; } } // namespace video } // namespace client