src/video/gl/gl_renderer.cpp

Go to the documentation of this file.
00001 //  SuperTux
00002 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
00003 //
00004 //  This program is free software: you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation, either version 3 of the License, or
00007 //  (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #include "video/gl/gl_renderer.hpp"
00018 
00019 #include <iomanip>
00020 #include <iostream>
00021 #include <physfs.h>
00022 
00023 #include "supertux/gameconfig.hpp"
00024 #include "supertux/globals.hpp"
00025 #include "video/drawing_request.hpp"
00026 #include "video/gl/gl_surface_data.hpp"
00027 #include "video/gl/gl_texture.hpp"
00028 #define LIGHTMAP_DIV 5
00029 
00030 #ifdef GL_VERSION_ES_CM_1_0
00031 #  define glOrtho glOrthof
00032 #endif
00033 
00034 GLRenderer::GLRenderer() :
00035   desktop_size(-1, -1),
00036   screen_size(-1, -1),
00037   fullscreen_active(false)
00038 {
00039   Renderer::instance_ = this;
00040 
00041 #if SDL_MAJOR_VERSION > 1 || SDL_MINOR_VERSION > 2 || (SDL_MINOR_VERSION == 2 && SDL_PATCHLEVEL >= 10)
00042   // unfortunately only newer SDLs have these infos.
00043   // This must be called before SDL_SetVideoMode() or it will return
00044   // the window size instead of the desktop size.
00045   const SDL_VideoInfo *info = SDL_GetVideoInfo();
00046   if (info)
00047   {
00048     desktop_size = Size(info->current_w, info->current_h);
00049   }
00050 #endif
00051 
00052   if(texture_manager != 0)
00053     texture_manager->save_textures();
00054 
00055 #ifdef SDL_GL_SWAP_CONTROL
00056   if(config->try_vsync) {
00057     /* we want vsync for smooth scrolling */
00058     SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
00059   }
00060 #endif
00061 
00062   SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
00063 
00064   // FIXME: Hu? 16bit rendering?
00065   SDL_GL_SetAttribute(SDL_GL_RED_SIZE,   5);
00066   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
00067   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,  5);
00068 
00069   if(g_config->use_fullscreen)
00070   {
00071     apply_video_mode(g_config->fullscreen_size, true);
00072   }
00073   else
00074   {
00075     apply_video_mode(g_config->window_size, false);
00076   }
00077 
00078   // setup opengl state and transform
00079   glDisable(GL_DEPTH_TEST);
00080   glDisable(GL_CULL_FACE);
00081   glEnable(GL_TEXTURE_2D);
00082   glEnable(GL_BLEND);
00083   glEnableClientState(GL_VERTEX_ARRAY);
00084   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00085   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00086 
00087   // Init the projection matrix, viewport and stuff
00088   apply_config();
00089   
00090   if(texture_manager == 0)
00091     texture_manager = new TextureManager();
00092   else
00093     texture_manager->reload_textures();
00094   
00095 #ifndef GL_VERSION_ES_CM_1_0
00096   GLenum err = glewInit();
00097   if (GLEW_OK != err)
00098   {
00099     std::ostringstream out;
00100     out << "GLRenderer: " << glewGetErrorString(err);
00101     throw std::runtime_error(out.str());
00102   }
00103   log_info << "Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;
00104   log_info << "GLEW_ARB_texture_non_power_of_two: " << static_cast<int>(GLEW_ARB_texture_non_power_of_two) << std::endl;
00105 #endif
00106 }
00107 
00108 GLRenderer::~GLRenderer()
00109 {
00110 }
00111 
00112 void
00113 GLRenderer::draw_surface(const DrawingRequest& request)
00114 {
00115   const Surface* surface = (const Surface*) request.request_data;
00116   GLTexture* gltexture = static_cast<GLTexture*>(surface->get_texture().get());
00117   GLSurfaceData *surface_data = static_cast<GLSurfaceData*>(surface->get_surface_data());
00118 
00119   glBindTexture(GL_TEXTURE_2D, gltexture->get_handle());
00120   intern_draw(request.pos.x, request.pos.y,
00121               request.pos.x + surface->get_width(),
00122               request.pos.y + surface->get_height(),
00123               surface_data->get_uv_left(),
00124               surface_data->get_uv_top(),
00125               surface_data->get_uv_right(),
00126               surface_data->get_uv_bottom(),
00127               request.angle,
00128               request.alpha,
00129               request.color,
00130               request.blend,
00131               request.drawing_effect);
00132 }
00133 
00134 void
00135 GLRenderer::draw_surface_part(const DrawingRequest& request)
00136 {
00137   const SurfacePartRequest* surfacepartrequest
00138     = (SurfacePartRequest*) request.request_data;
00139   const Surface* surface = surfacepartrequest->surface;
00140   boost::shared_ptr<GLTexture> gltexture = boost::dynamic_pointer_cast<GLTexture>(surface->get_texture());
00141   GLSurfaceData *surface_data = reinterpret_cast<GLSurfaceData *>(surface->get_surface_data());
00142 
00143   float uv_width = surface_data->get_uv_right() - surface_data->get_uv_left();
00144   float uv_height = surface_data->get_uv_bottom() - surface_data->get_uv_top();
00145 
00146   float uv_left = surface_data->get_uv_left() + (uv_width * surfacepartrequest->source.x) / surface->get_width();
00147   float uv_top = surface_data->get_uv_top() + (uv_height * surfacepartrequest->source.y) / surface->get_height();
00148   float uv_right = surface_data->get_uv_left() + (uv_width * (surfacepartrequest->source.x + surfacepartrequest->size.x)) / surface->get_width();
00149   float uv_bottom = surface_data->get_uv_top() + (uv_height * (surfacepartrequest->source.y + surfacepartrequest->size.y)) / surface->get_height();
00150 
00151   glBindTexture(GL_TEXTURE_2D, gltexture->get_handle());
00152   intern_draw(request.pos.x, request.pos.y,
00153               request.pos.x + surfacepartrequest->size.x,
00154               request.pos.y + surfacepartrequest->size.y,
00155               uv_left,
00156               uv_top,
00157               uv_right,
00158               uv_bottom,
00159               0.0,
00160               request.alpha,
00161               request.color,
00162               Blend(),
00163               request.drawing_effect);
00164 }
00165 
00166 void
00167 GLRenderer::draw_gradient(const DrawingRequest& request)
00168 {
00169   const GradientRequest* gradientrequest 
00170     = (GradientRequest*) request.request_data;
00171   const Color& top = gradientrequest->top;
00172   const Color& bottom = gradientrequest->bottom;
00173 
00174   glDisable(GL_TEXTURE_2D);
00175   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00176   glEnableClientState(GL_COLOR_ARRAY);
00177 
00178   float vertices[] = {
00179     0, 0,
00180     SCREEN_WIDTH, 0,
00181     SCREEN_WIDTH, SCREEN_HEIGHT,
00182     0, SCREEN_HEIGHT
00183   };
00184   glVertexPointer(2, GL_FLOAT, 0, vertices);
00185 
00186   float colors[] = {
00187     top.red, top.green, top.blue, top.alpha,
00188     top.red, top.green, top.blue, top.alpha,
00189     bottom.red, bottom.green, bottom.blue, bottom.alpha,
00190     bottom.red, bottom.green, bottom.blue, bottom.alpha,
00191   };
00192   glColorPointer(4, GL_FLOAT, 0, colors);
00193 
00194   glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
00195 
00196   glDisableClientState(GL_COLOR_ARRAY);
00197   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00198 
00199   glEnable(GL_TEXTURE_2D);
00200   glColor4f(1, 1, 1, 1);
00201 }
00202 
00203 void
00204 GLRenderer::draw_filled_rect(const DrawingRequest& request)
00205 {
00206   const FillRectRequest* fillrectrequest
00207     = (FillRectRequest*) request.request_data;
00208 
00209   glDisable(GL_TEXTURE_2D);
00210   glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
00211             fillrectrequest->color.blue, fillrectrequest->color.alpha);
00212   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00213   
00214   if (fillrectrequest->radius != 0.0f)
00215   {
00216     // draw round rect
00217     // Keep radius in the limits, so that we get a circle instead of
00218     // just graphic junk
00219     float radius = std::min(fillrectrequest->radius,
00220                             std::min(fillrectrequest->size.x/2,
00221                                      fillrectrequest->size.y/2));
00222 
00223     // inner rectangle
00224     Rectf irect(request.pos.x    + radius,
00225                request.pos.y    + radius,
00226                request.pos.x + fillrectrequest->size.x - radius,
00227                request.pos.y + fillrectrequest->size.y - radius);
00228 
00229     int n = 8;
00230     int p = 0;
00231     std::vector<float> vertices((n+1) * 4 * 2);
00232 
00233     for(int i = 0; i <= n; ++i)
00234     {
00235       float x = sinf(i * (M_PI/2) / n) * radius;
00236       float y = cosf(i * (M_PI/2) / n) * radius;
00237 
00238       vertices[p++] = irect.get_left() - x;
00239       vertices[p++] = irect.get_top()  - y;
00240 
00241       vertices[p++] = irect.get_right() + x;
00242       vertices[p++] = irect.get_top()   - y;
00243     }
00244 
00245     for(int i = 0; i <= n; ++i)
00246     {
00247       float x = cosf(i * (M_PI/2) / n) * radius;
00248       float y = sinf(i * (M_PI/2) / n) * radius;
00249 
00250       vertices[p++] = irect.get_left()   - x;
00251       vertices[p++] = irect.get_bottom() + y;
00252 
00253       vertices[p++] = irect.get_right()  + x;
00254       vertices[p++] = irect.get_bottom() + y;
00255     }
00256 
00257     glVertexPointer(2, GL_FLOAT, 0, &*vertices.begin());
00258     glDrawArrays(GL_TRIANGLE_STRIP, 0,  vertices.size()/2);
00259   }
00260   else
00261   {
00262     float x = request.pos.x;
00263     float y = request.pos.y;
00264     float w = fillrectrequest->size.x;
00265     float h = fillrectrequest->size.y;
00266 
00267     float vertices[] = {
00268       x,   y,
00269       x+w, y,
00270       x+w, y+h,
00271       x,   y+h
00272     };
00273     glVertexPointer(2, GL_FLOAT, 0, vertices);
00274 
00275     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
00276   }
00277 
00278   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00279   glEnable(GL_TEXTURE_2D);
00280   glColor4f(1, 1, 1, 1);
00281 }
00282 
00283 void
00284 GLRenderer::draw_inverse_ellipse(const DrawingRequest& request)
00285 {
00286   const InverseEllipseRequest* ellipse = (InverseEllipseRequest*)request.request_data;
00287 
00288   glDisable(GL_TEXTURE_2D);
00289   glColor4f(ellipse->color.red,  ellipse->color.green,
00290             ellipse->color.blue, ellipse->color.alpha);
00291     
00292   float x = request.pos.x;
00293   float y = request.pos.y;
00294   float w = ellipse->size.x/2.0f;
00295   float h = ellipse->size.y/2.0f;
00296 
00297   static const int slices = 16;
00298   static const int points = (slices+1) * 12;
00299 
00300   float vertices[points * 2];
00301   int   p = 0;
00302 
00303   // Bottom
00304   vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT;
00305   vertices[p++] = 0;            vertices[p++] = SCREEN_HEIGHT;
00306   vertices[p++] = x;            vertices[p++] = y+h;
00307 
00308   // Top
00309   vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0;
00310   vertices[p++] = 0;            vertices[p++] = 0;
00311   vertices[p++] = x;            vertices[p++] = y-h;
00312 
00313   // Left
00314   vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0;
00315   vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT;
00316   vertices[p++] = x+w;          vertices[p++] = y;
00317 
00318   // Right
00319   vertices[p++] = 0;            vertices[p++] = 0;
00320   vertices[p++] = 0;            vertices[p++] = SCREEN_HEIGHT;
00321   vertices[p++] = x-w;          vertices[p++] = y;
00322 
00323   for(int i = 0; i < slices; ++i)
00324   {
00325     float ex1 = sinf(M_PI/2 / slices * i) * w;
00326     float ey1 = cosf(M_PI/2 / slices * i) * h;
00327 
00328     float ex2 = sinf(M_PI/2 / slices * (i+1)) * w;
00329     float ey2 = cosf(M_PI/2 / slices * (i+1)) * h;
00330 
00331     // Bottom/Right
00332     vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT;
00333     vertices[p++] = x + ex1;      vertices[p++] = y + ey1;
00334     vertices[p++] = x + ex2;      vertices[p++] = y + ey2;
00335 
00336     // Top/Left
00337     vertices[p++] = 0;            vertices[p++] = 0;
00338     vertices[p++] = x - ex1;      vertices[p++] = y - ey1;
00339     vertices[p++] = x - ex2;      vertices[p++] = y - ey2;
00340 
00341     // Top/Right
00342     vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0;
00343     vertices[p++] = x + ex1;      vertices[p++] = y - ey1;
00344     vertices[p++] = x + ex2;      vertices[p++] = y - ey2;
00345 
00346     // Bottom/Left
00347     vertices[p++] = 0;            vertices[p++] = SCREEN_HEIGHT;
00348     vertices[p++] = x - ex1;      vertices[p++] = y + ey1;
00349     vertices[p++] = x - ex2;      vertices[p++] = y + ey2;
00350   }
00351 
00352   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00353   glVertexPointer(2, GL_FLOAT, 0, vertices);
00354 
00355   glDrawArrays(GL_TRIANGLES, 0, points);
00356 
00357   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00358 
00359   glEnable(GL_TEXTURE_2D);
00360   glColor4f(1, 1, 1, 1);    
00361 }
00362 
00363 void 
00364 GLRenderer::do_take_screenshot()
00365 {
00366   // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
00367 
00368   SDL_Surface *shot_surf;
00369   // create surface to hold screenshot
00370 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00371   shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
00372 #else
00373   shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
00374 #endif
00375   if (!shot_surf) {
00376     log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
00377     return;
00378   }
00379 
00380   // read pixels into array
00381   char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
00382   if (!pixels) {
00383     log_warning << "Could not allocate memory to store screenshot" << std::endl;
00384     SDL_FreeSurface(shot_surf);
00385     return;
00386   }
00387   glPixelStorei(GL_PACK_ALIGNMENT, 1);
00388   glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
00389 
00390   // copy array line-by-line
00391   for (int i = 0; i < SCREEN_HEIGHT; i++) {
00392     char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
00393     if(SDL_MUSTLOCK(shot_surf))
00394     {
00395       SDL_LockSurface(shot_surf);
00396     }
00397     char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
00398     memcpy(dst, src, 3 * SCREEN_WIDTH);
00399     if(SDL_MUSTLOCK(shot_surf))
00400     {
00401       SDL_UnlockSurface(shot_surf);
00402     }
00403   }
00404 
00405   // free array
00406   delete[](pixels);
00407 
00408   // save screenshot
00409   static const std::string writeDir = PHYSFS_getWriteDir();
00410   static const std::string dirSep = PHYSFS_getDirSeparator();
00411   static const std::string baseName = "screenshot";
00412   static const std::string fileExt = ".bmp";
00413   std::string fullFilename;
00414   for (int num = 0; num < 1000; num++) {
00415     std::ostringstream oss;
00416     oss << baseName;
00417     oss << std::setw(3) << std::setfill('0') << num;
00418     oss << fileExt;
00419     std::string fileName = oss.str();
00420     fullFilename = writeDir + dirSep + fileName;
00421     if (!PHYSFS_exists(fileName.c_str())) {
00422       SDL_SaveBMP(shot_surf, fullFilename.c_str());
00423       log_debug << "Wrote screenshot to \"" << fullFilename << "\"" << std::endl;
00424       SDL_FreeSurface(shot_surf);
00425       return;
00426     }
00427   }
00428   log_warning << "Did not save screenshot, because all files up to \"" << fullFilename << "\" already existed" << std::endl;
00429   SDL_FreeSurface(shot_surf);
00430 }
00431 
00432 void
00433 GLRenderer::flip()
00434 {
00435   assert_gl("drawing");
00436   SDL_GL_SwapBuffers();
00437 }
00438 
00439 void
00440 GLRenderer::resize(int w, int h)
00441 {
00442   // This causes the screen to go black, which is annoying, but seems
00443   // unavoidable with SDL at the moment
00444   SDL_SetVideoMode(w, h, 0, SDL_OPENGL | SDL_RESIZABLE);
00445 
00446   g_config->window_size = Size(w, h);
00447 
00448   apply_config();
00449 }
00450 
00451 void
00452 GLRenderer::apply_config()
00453 {    
00454   if (false)
00455   {
00456     log_info << "Applying Config:" 
00457              << "\n  Desktop: " << desktop_size.width << "x" << desktop_size.height
00458              << "\n  Window:  " << g_config->window_size
00459              << "\n  FullRes: " << g_config->fullscreen_size
00460              << "\n  Aspect:  " << g_config->aspect_size
00461              << "\n  Magnif:  " << g_config->magnification
00462              << std::endl;
00463   }
00464 
00465   float target_aspect = static_cast<float>(desktop_size.width) / static_cast<float>(desktop_size.height);
00466   if (g_config->aspect_size != Size(0, 0))
00467   {
00468     target_aspect = float(g_config->aspect_size.width) / float(g_config->aspect_size.height);
00469   }
00470 
00471   float desktop_aspect = 4.0f / 3.0f; // random default fallback guess
00472   if (desktop_size.width != -1 && desktop_size.height != -1)
00473   {
00474     desktop_aspect = float(desktop_size.width) / float(desktop_size.height);
00475   }
00476 
00477   Size screen_size;
00478 
00479   // Get the screen width
00480   if (g_config->use_fullscreen)
00481   {
00482     screen_size = g_config->fullscreen_size;
00483     desktop_aspect = float(screen_size.width) / float(screen_size.height);
00484   }
00485   else
00486   {
00487     screen_size = g_config->window_size;
00488   }
00489 
00490   apply_video_mode(screen_size, g_config->use_fullscreen);
00491 
00492   if (target_aspect > 1.0f)
00493   {
00494     SCREEN_WIDTH  = static_cast<int>(screen_size.width * (target_aspect / desktop_aspect));
00495     SCREEN_HEIGHT = static_cast<int>(screen_size.height);
00496   }
00497   else
00498   {
00499     SCREEN_WIDTH  = static_cast<int>(screen_size.width);
00500     SCREEN_HEIGHT = static_cast<int>(screen_size.height  * (target_aspect / desktop_aspect));
00501   }
00502 
00503   Size max_size(1280, 800);
00504   Size min_size(640, 480);
00505 
00506   if (g_config->magnification == 0.0f) // Magic value that means 'minfill'
00507   {
00508     // This scales SCREEN_WIDTH/SCREEN_HEIGHT so that they never excede
00509     // max_size.width/max_size.height resp. min_size.width/min_size.height
00510     if (SCREEN_WIDTH > max_size.width || SCREEN_HEIGHT > max_size.height)
00511     {
00512       float scale1  = float(max_size.width)/SCREEN_WIDTH;
00513       float scale2  = float(max_size.height)/SCREEN_HEIGHT;
00514       float scale   = (scale1 < scale2) ? scale1 : scale2;
00515       SCREEN_WIDTH  = static_cast<int>(SCREEN_WIDTH  * scale);
00516       SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT * scale);
00517     } 
00518     else if (SCREEN_WIDTH < min_size.width || SCREEN_HEIGHT < min_size.height)
00519     {
00520       float scale1  = float(min_size.width)/SCREEN_WIDTH;
00521       float scale2  = float(min_size.height)/SCREEN_HEIGHT;
00522       float scale   = (scale1 < scale2) ? scale1 : scale2;
00523       SCREEN_WIDTH  = static_cast<int>(SCREEN_WIDTH  * scale);
00524       SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT * scale);
00525     }
00526    
00527 
00528     glViewport(0, 0, screen_size.width, screen_size.height);
00529   }
00530   else
00531   {
00532     SCREEN_WIDTH  = static_cast<int>(SCREEN_WIDTH  / g_config->magnification);
00533     SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT / g_config->magnification);
00534 
00535     // This works by adding black borders around the screen to limit
00536     // SCREEN_WIDTH/SCREEN_HEIGHT to max_size.width/max_size.height
00537     Size new_size = screen_size;
00538 
00539     if (SCREEN_WIDTH > max_size.width)
00540     {
00541       new_size.width = static_cast<int>((float) new_size.width * float(max_size.width)/SCREEN_WIDTH);
00542       SCREEN_WIDTH = static_cast<int>(max_size.width);
00543     }
00544 
00545     if (SCREEN_HEIGHT > max_size.height)
00546     {
00547       new_size.height = static_cast<int>((float) new_size.height * float(max_size.height)/SCREEN_HEIGHT);
00548       SCREEN_HEIGHT = static_cast<int>(max_size.height);
00549     }
00550 
00551     // Clear both buffers so that we get a clean black border without junk
00552     glClear(GL_COLOR_BUFFER_BIT);
00553     SDL_GL_SwapBuffers();
00554     glClear(GL_COLOR_BUFFER_BIT);
00555     SDL_GL_SwapBuffers();
00556 
00557     glViewport(std::max(0, (screen_size.width  - new_size.width)  / 2),
00558                std::max(0, (screen_size.height - new_size.height) / 2),
00559                std::min(new_size.width,  screen_size.width),
00560                std::min(new_size.height, screen_size.height));
00561   }
00562 
00563   glMatrixMode(GL_PROJECTION);
00564   glLoadIdentity();
00565 
00566   glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1, 1);
00567 
00568   glMatrixMode(GL_MODELVIEW);
00569   glLoadIdentity();
00570   glTranslatef(0, 0, 0);
00571   check_gl_error("Setting up view matrices");
00572 }
00573 
00574 void
00575 GLRenderer::apply_video_mode(const Size& size, bool fullscreen)
00576 {
00577   // Only change video mode when its different from the current one
00578   if (screen_size != size || fullscreen_active != fullscreen)
00579   {
00580     int flags = SDL_OPENGL;
00581 
00582     if (fullscreen)
00583     {
00584       flags |= SDL_FULLSCREEN;
00585     }
00586     else
00587     {
00588       flags |= SDL_RESIZABLE;
00589     }
00590 
00591     if (SDL_Surface *screen = SDL_SetVideoMode(size.width, size.height, 0, flags))
00592     {
00593       screen_size = Size(screen->w, screen->h);
00594       fullscreen_active = fullscreen; 
00595     }
00596     else
00597     {
00598       std::ostringstream msg;
00599       msg << "Couldn't set video mode " << size.width << "x" << size.height << ": " << SDL_GetError();
00600       throw std::runtime_error(msg.str());
00601     }
00602   }
00603 }
00604 
00605 /* EOF */

Generated on Mon Apr 21 03:38:18 2014 for SuperTux by  doxygen 1.5.1