From 2ee1a7c6335e6055268134890c8fe294e19af695 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Wed, 14 May 2008 22:23:35 +0000 Subject: [PATCH] Patched some aspect ratio back in (PS: screwed up code indention a bit) SVN-Revision: 5477 --- src/options_menu.cpp | 50 +-- src/video/gl_renderer.cpp | 744 ++++++++++++++++++++++++--------------------- src/video/gl_renderer.hpp | 5 + src/video/renderer.hpp | 1 + src/video/sdl_renderer.hpp | 1 + 5 files changed, 426 insertions(+), 375 deletions(-) diff --git a/src/options_menu.cpp b/src/options_menu.cpp index 778f77cd4..0847417bf 100644 --- a/src/options_menu.cpp +++ b/src/options_menu.cpp @@ -26,6 +26,7 @@ #include "control/joystickkeyboardcontroller.hpp" #include "main.hpp" #include "gettext.hpp" +#include "video/renderer.hpp" #include "gameconfig.hpp" Menu* options_menu = 0; @@ -33,7 +34,7 @@ Menu* options_menu = 0; enum OptionsMenuIDs { MNID_FULLSCREEN, MNID_FULLSCREEN_RESOLUTION, - MNID_PROJECTION_AREA, + MNID_MAGINFICATION, MNID_ASPECTRATIO, MNID_SOUND, MNID_MUSIC @@ -125,23 +126,17 @@ OptionsMenu::OptionsMenu() add_toggle(MNID_FULLSCREEN,_("Fullscreen"), config->use_fullscreen) ->set_help(_("Let the game cover the whole screen")); - MenuItem* projection = add_string_select(MNID_PROJECTION_AREA, _("Projection Area")); - projection->set_help(_("Change the visible area")); + MenuItem* maginfication = add_string_select(MNID_MAGINFICATION, _("Maginfication")); + maginfication->set_help(_("Change the magnification, to small values will result in a black border around the screen")); - projection->list.push_back("640x480"); - projection->list.push_back("800x600"); - projection->list.push_back("1024x768"); - projection->list.push_back("1152x864"); - projection->list.push_back("1280x960"); - projection->list.push_back("1280x1024"); - projection->list.push_back("1440x900"); - projection->list.push_back("1680x1050"); - projection->list.push_back("1600x1200"); - projection->list.push_back("1920x1080"); - projection->list.push_back("1920x1200"); + maginfication->list.push_back("-2"); + maginfication->list.push_back("-1"); + maginfication->list.push_back("0"); + maginfication->list.push_back("1"); + maginfication->list.push_back("2"); - MenuItem* fullscreen_res = add_string_select(MNID_FULLSCREEN_RESOLUTION, _("Fullscreen Resolution")); - fullscreen_res->set_help(_("Change the Fullscreen Resolution")); + MenuItem* fullscreen_res = add_string_select(MNID_FULLSCREEN_RESOLUTION, _("Resolution")); + fullscreen_res->set_help(_("Change the Resolution to be used in Fullscreen Mode, you have to toggle fullscreen mode to let this change take effect")); // FIXME: Hardcoded values are evil, these should be queried from the Xorg server fullscreen_res->list.push_back("640x480"); @@ -159,10 +154,10 @@ OptionsMenu::OptionsMenu() MenuItem* aspect = add_string_select(MNID_ASPECTRATIO, _("Aspect Ratio")); aspect->set_help(_("Adjust the aspect ratio")); - aspect->list.push_back("16:9"); - aspect->list.push_back("16:10"); aspect->list.push_back("4:3"); aspect->list.push_back("5:4"); + aspect->list.push_back("16:10"); + aspect->list.push_back("16:9"); std::ostringstream out; out << config->aspect_width << ":" << config->aspect_height; @@ -211,25 +206,12 @@ OptionsMenu::menu_action(MenuItem* item) switch (item->id) { case MNID_ASPECTRATIO: { // FIXME: Really crude and ugly here, move to video or so - if(sscanf(item->list[item->selected].c_str(), "%d:%d", &config->aspect_width, &config->aspect_height) == 2) + if(sscanf(item->list[item->selected].c_str(), "%d:%d", &config->aspect_width, &config->aspect_height) == 2) { - float aspect_ratio = static_cast(config->aspect_width) / - static_cast(config->aspect_height); - - if (aspect_ratio > 1) { - SCREEN_WIDTH = static_cast (600 * aspect_ratio + 0.5); - SCREEN_HEIGHT = 600; - } else { - SCREEN_WIDTH = 600; - SCREEN_HEIGHT = static_cast (600 * 1/aspect_ratio + 0.5); - } - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0); - std::cout << __FILE__ << ":" << __LINE__ << ": change aspect ratio to " << item->list[item->selected] << std::endl; + Renderer::instance()->apply_config(); // Reposition the menu to be in the center of the screen again + // FIXME: We need to relayout the whole menu stack! Not just current set_pos(SCREEN_WIDTH/2, SCREEN_HEIGHT/2); } } diff --git a/src/video/gl_renderer.cpp b/src/video/gl_renderer.cpp index 8f4fbedb6..3632471ad 100644 --- a/src/video/gl_renderer.cpp +++ b/src/video/gl_renderer.cpp @@ -120,395 +120,457 @@ inline void intern_draw(float left, float top, float right, float bottom, } } -namespace GL -{ - Renderer::Renderer() - { - ::Renderer::instance_ = this; - - if(texture_manager != 0) - texture_manager->save_textures(); +namespace GL { - if(config->try_vsync) { - /* we want vsync for smooth scrolling */ - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); +Renderer::Renderer() + : desktop_width(-1), + desktop_height(-1) +{ + ::Renderer::instance_ = this; + +#if SDL_MAJOR_VERSION > 1 || SDL_MINOR_VERSION > 2 || (SDL_MINOR_VERSION == 2 && SDL_PATCHLEVEL >= 10) + // unfortunately only newer SDLs have these infos. + // This must be called before SDL_SetVideoMode() or it will return + // the window size instead of the desktop size. + const SDL_VideoInfo *info = SDL_GetVideoInfo(); + if (info) + { + desktop_width = info->current_w; + desktop_height = info->current_h; } +#endif - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + if(texture_manager != 0) + texture_manager->save_textures(); - // Hu? 16bit rendering? - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); + if(config->try_vsync) { + /* we want vsync for smooth scrolling */ + SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); + } - int flags = SDL_OPENGL; - int width; - int height; - if(config->use_fullscreen) - { - flags |= SDL_FULLSCREEN; - width = config->fullscreen_width; - height = config->fullscreen_height; - } - else - { - flags |= SDL_RESIZABLE; - width = config->window_width; - height = config->window_height; - } - int bpp = 0; - - SDL_Surface *screen = SDL_SetVideoMode(width, height, bpp, flags); - if(screen == 0) { - std::stringstream msg; - msg << "Couldn't set video mode (" << width << "x" << height - << "-" << bpp << "bpp): " << SDL_GetError(); - throw std::runtime_error(msg.str()); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + // Hu? 16bit rendering? + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); + + int flags = SDL_OPENGL; + int width; + int height; + if(config->use_fullscreen) + { + flags |= SDL_FULLSCREEN; + width = config->fullscreen_width; + height = config->fullscreen_height; } + else + { + flags |= SDL_RESIZABLE; + width = config->window_width; + height = config->window_height; + } + int bpp = 0; + + SDL_Surface *screen = SDL_SetVideoMode(width, height, bpp, flags); + if(screen == 0) { + std::stringstream msg; + msg << "Couldn't set video mode (" << width << "x" << height + << "-" << bpp << "bpp): " << SDL_GetError(); + throw std::runtime_error(msg.str()); + } - // setup opengl state and transform - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // setup opengl state and transform + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glViewport(0, 0, screen->w, screen->h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); + glViewport(0, 0, screen->w, screen->h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); - // logical resolution here not real monitor resolution - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0); + // logical resolution here not real monitor resolution + glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0, 0, 0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, 0); - check_gl_error("Setting up view matrices"); + check_gl_error("Setting up view matrices"); - if(texture_manager == 0) - texture_manager = new TextureManager(); - else - texture_manager->reload_textures(); - } + if(texture_manager == 0) + texture_manager = new TextureManager(); + else + texture_manager->reload_textures(); +} - Renderer::~Renderer() - { - } +Renderer::~Renderer() +{ +} - void - Renderer::draw_surface(const DrawingRequest& request) - { - const Surface* surface = (const Surface*) request.request_data; - GL::Texture *gltexture = dynamic_cast(surface->get_texture()); - GL::SurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); - - glBindTexture(GL_TEXTURE_2D, gltexture->get_handle()); - intern_draw(request.pos.x, request.pos.y, - request.pos.x + surface->get_width(), - request.pos.y + surface->get_height(), - surface_data->get_uv_left(), - surface_data->get_uv_top(), - surface_data->get_uv_right(), - surface_data->get_uv_bottom(), - request.angle, - request.alpha, - request.color, - request.blend, - request.drawing_effect); - } +void +Renderer::draw_surface(const DrawingRequest& request) +{ + const Surface* surface = (const Surface*) request.request_data; + GL::Texture *gltexture = dynamic_cast(surface->get_texture()); + GL::SurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); + + glBindTexture(GL_TEXTURE_2D, gltexture->get_handle()); + intern_draw(request.pos.x, request.pos.y, + request.pos.x + surface->get_width(), + request.pos.y + surface->get_height(), + surface_data->get_uv_left(), + surface_data->get_uv_top(), + surface_data->get_uv_right(), + surface_data->get_uv_bottom(), + request.angle, + request.alpha, + request.color, + request.blend, + request.drawing_effect); +} - void - Renderer::draw_surface_part(const DrawingRequest& request) - { - const SurfacePartRequest* surfacepartrequest - = (SurfacePartRequest*) request.request_data; - const Surface *surface = surfacepartrequest->surface; - GL::Texture *gltexture = dynamic_cast(surface->get_texture()); - GL::SurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); - - float uv_width = surface_data->get_uv_right() - surface_data->get_uv_left(); - float uv_height = surface_data->get_uv_bottom() - surface_data->get_uv_top(); - - float uv_left = surface_data->get_uv_left() + (uv_width * surfacepartrequest->source.x) / surface->get_width(); - float uv_top = surface_data->get_uv_top() + (uv_height * surfacepartrequest->source.y) / surface->get_height(); - float uv_right = surface_data->get_uv_left() + (uv_width * (surfacepartrequest->source.x + surfacepartrequest->size.x)) / surface->get_width(); - float uv_bottom = surface_data->get_uv_top() + (uv_height * (surfacepartrequest->source.y + surfacepartrequest->size.y)) / surface->get_height(); - - glBindTexture(GL_TEXTURE_2D, gltexture->get_handle()); - intern_draw(request.pos.x, request.pos.y, - request.pos.x + surfacepartrequest->size.x, - request.pos.y + surfacepartrequest->size.y, - uv_left, - uv_top, - uv_right, - uv_bottom, - 0.0, - request.alpha, - Color(1.0, 1.0, 1.0), - Blend(), - request.drawing_effect); - } +void +Renderer::draw_surface_part(const DrawingRequest& request) +{ + const SurfacePartRequest* surfacepartrequest + = (SurfacePartRequest*) request.request_data; + const Surface *surface = surfacepartrequest->surface; + GL::Texture *gltexture = dynamic_cast(surface->get_texture()); + GL::SurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); + + float uv_width = surface_data->get_uv_right() - surface_data->get_uv_left(); + float uv_height = surface_data->get_uv_bottom() - surface_data->get_uv_top(); + + float uv_left = surface_data->get_uv_left() + (uv_width * surfacepartrequest->source.x) / surface->get_width(); + float uv_top = surface_data->get_uv_top() + (uv_height * surfacepartrequest->source.y) / surface->get_height(); + float uv_right = surface_data->get_uv_left() + (uv_width * (surfacepartrequest->source.x + surfacepartrequest->size.x)) / surface->get_width(); + float uv_bottom = surface_data->get_uv_top() + (uv_height * (surfacepartrequest->source.y + surfacepartrequest->size.y)) / surface->get_height(); + + glBindTexture(GL_TEXTURE_2D, gltexture->get_handle()); + intern_draw(request.pos.x, request.pos.y, + request.pos.x + surfacepartrequest->size.x, + request.pos.y + surfacepartrequest->size.y, + uv_left, + uv_top, + uv_right, + uv_bottom, + 0.0, + request.alpha, + Color(1.0, 1.0, 1.0), + Blend(), + request.drawing_effect); +} - void - Renderer::draw_gradient(const DrawingRequest& request) - { - const GradientRequest* gradientrequest - = (GradientRequest*) request.request_data; - const Color& top = gradientrequest->top; - const Color& bottom = gradientrequest->bottom; - - glDisable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - glColor4f(top.red, top.green, top.blue, top.alpha); - glVertex2f(0, 0); - glVertex2f(SCREEN_WIDTH, 0); - glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha); - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT); - glVertex2f(0, SCREEN_HEIGHT); - glEnd(); - glEnable(GL_TEXTURE_2D); - glColor4f(1, 1, 1, 1); - } +void +Renderer::draw_gradient(const DrawingRequest& request) +{ + const GradientRequest* gradientrequest + = (GradientRequest*) request.request_data; + const Color& top = gradientrequest->top; + const Color& bottom = gradientrequest->bottom; + + glDisable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + glColor4f(top.red, top.green, top.blue, top.alpha); + glVertex2f(0, 0); + glVertex2f(SCREEN_WIDTH, 0); + glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha); + glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT); + glVertex2f(0, SCREEN_HEIGHT); + glEnd(); + glEnable(GL_TEXTURE_2D); + glColor4f(1, 1, 1, 1); +} + +void +Renderer::draw_filled_rect(const DrawingRequest& request) +{ + const FillRectRequest* fillrectrequest + = (FillRectRequest*) request.request_data; + + if (fillrectrequest->radius != 0.0f) + { + // draw round rect + // Keep radius in the limits, so that we get a circle instead of + // just graphic junk + float radius = std::min(fillrectrequest->radius, + std::min(fillrectrequest->size.x/2, + fillrectrequest->size.y/2)); + + // inner rectangle + Rect irect(request.pos.x + radius, + request.pos.y + radius, + request.pos.x + fillrectrequest->size.x - radius, + request.pos.y + fillrectrequest->size.y - radius); + + glDisable(GL_TEXTURE_2D); + glColor4f(fillrectrequest->color.red, fillrectrequest->color.green, + fillrectrequest->color.blue, fillrectrequest->color.alpha); + + + int n = 8; + glBegin(GL_QUAD_STRIP); + for(int i = 0; i <= n; ++i) + { + float x = sinf(i * (M_PI/2) / n) * radius; + float y = cosf(i * (M_PI/2) / n) * radius; + + glVertex2f(irect.get_left() - x, irect.get_top() - y); + glVertex2f(irect.get_right() + x, irect.get_top() - y); + } + for(int i = 0; i <= n; ++i) + { + float x = cosf(i * (M_PI/2) / n) * radius; + float y = sinf(i * (M_PI/2) / n) * radius; + + glVertex2f(irect.get_left() - x, irect.get_bottom() + y); + glVertex2f(irect.get_right() + x, irect.get_bottom() + y); + } + glEnd(); + glEnable(GL_TEXTURE_2D); + glColor4f(1, 1, 1, 1); + } + else + { + float x = request.pos.x; + float y = request.pos.y; + float w = fillrectrequest->size.x; + float h = fillrectrequest->size.y; - void - Renderer::draw_filled_rect(const DrawingRequest& request) - { - const FillRectRequest* fillrectrequest - = (FillRectRequest*) request.request_data; + glDisable(GL_TEXTURE_2D); + glColor4f(fillrectrequest->color.red, fillrectrequest->color.green, + fillrectrequest->color.blue, fillrectrequest->color.alpha); - if (fillrectrequest->radius != 0.0f) - { - // draw round rect - // Keep radius in the limits, so that we get a circle instead of - // just graphic junk - float radius = std::min(fillrectrequest->radius, - std::min(fillrectrequest->size.x/2, - fillrectrequest->size.y/2)); - - // inner rectangle - Rect irect(request.pos.x + radius, - request.pos.y + radius, - request.pos.x + fillrectrequest->size.x - radius, - request.pos.y + fillrectrequest->size.y - radius); - - glDisable(GL_TEXTURE_2D); - glColor4f(fillrectrequest->color.red, fillrectrequest->color.green, - fillrectrequest->color.blue, fillrectrequest->color.alpha); - - - int n = 8; - glBegin(GL_QUAD_STRIP); - for(int i = 0; i <= n; ++i) - { - float x = sinf(i * (M_PI/2) / n) * radius; - float y = cosf(i * (M_PI/2) / n) * radius; - - glVertex2f(irect.get_left() - x, irect.get_top() - y); - glVertex2f(irect.get_right() + x, irect.get_top() - y); - } - for(int i = 0; i <= n; ++i) - { - float x = cosf(i * (M_PI/2) / n) * radius; - float y = sinf(i * (M_PI/2) / n) * radius; - - glVertex2f(irect.get_left() - x, irect.get_bottom() + y); - glVertex2f(irect.get_right() + x, irect.get_bottom() + y); - } - glEnd(); - glEnable(GL_TEXTURE_2D); - glColor4f(1, 1, 1, 1); - } - else - { - float x = request.pos.x; - float y = request.pos.y; - float w = fillrectrequest->size.x; - float h = fillrectrequest->size.y; - - glDisable(GL_TEXTURE_2D); - glColor4f(fillrectrequest->color.red, fillrectrequest->color.green, - fillrectrequest->color.blue, fillrectrequest->color.alpha); - - glBegin(GL_QUADS); - glVertex2f(x, y); - glVertex2f(x+w, y); - glVertex2f(x+w, y+h); - glVertex2f(x, y+h); - glEnd(); - glEnable(GL_TEXTURE_2D); - glColor4f(1, 1, 1, 1); - } - } + glBegin(GL_QUADS); + glVertex2f(x, y); + glVertex2f(x+w, y); + glVertex2f(x+w, y+h); + glVertex2f(x, y+h); + glEnd(); + glEnable(GL_TEXTURE_2D); + glColor4f(1, 1, 1, 1); + } +} - void - Renderer::draw_inverse_ellipse(const DrawingRequest& request) - { - const InverseEllipseRequest* ellipse = (InverseEllipseRequest*)request.request_data; +void +Renderer::draw_inverse_ellipse(const DrawingRequest& request) +{ + const InverseEllipseRequest* ellipse = (InverseEllipseRequest*)request.request_data; - glDisable(GL_TEXTURE_2D); - glColor4f(ellipse->color.red, ellipse->color.green, - ellipse->color.blue, ellipse->color.alpha); + glDisable(GL_TEXTURE_2D); + glColor4f(ellipse->color.red, ellipse->color.green, + ellipse->color.blue, ellipse->color.alpha); - float x = request.pos.x; - float y = request.pos.y; - float w = ellipse->size.x/2.0f; - float h = ellipse->size.y/2.0f; + float x = request.pos.x; + float y = request.pos.y; + float w = ellipse->size.x/2.0f; + float h = ellipse->size.y/2.0f; - glBegin(GL_TRIANGLES); + glBegin(GL_TRIANGLES); - // Bottom - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT); - glVertex2f(0, SCREEN_HEIGHT); - glVertex2f(x, y+h); - - // Top - glVertex2f(SCREEN_WIDTH, 0); - glVertex2f(0, 0); - glVertex2f(x, y-h); - - // Left - glVertex2f(SCREEN_WIDTH, 0); - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT); - glVertex2f(x+w, y); - - // Right - glVertex2f(0, 0); - glVertex2f(0, SCREEN_HEIGHT); - glVertex2f(x-w, y); - - glEnd(); + // Bottom + glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT); + glVertex2f(0, SCREEN_HEIGHT); + glVertex2f(x, y+h); + + // Top + glVertex2f(SCREEN_WIDTH, 0); + glVertex2f(0, 0); + glVertex2f(x, y-h); + + // Left + glVertex2f(SCREEN_WIDTH, 0); + glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT); + glVertex2f(x+w, y); + + // Right + glVertex2f(0, 0); + glVertex2f(0, SCREEN_HEIGHT); + glVertex2f(x-w, y); + + glEnd(); - int slices = 16; - for(int i = 0; i < slices; ++i) - { - float ex1 = sinf(M_PI/2 / slices * i) * w; - float ey1 = cosf(M_PI/2 / slices * i) * h; - - float ex2 = sinf(M_PI/2 / slices * (i+1)) * w; - float ey2 = cosf(M_PI/2 / slices * (i+1)) * h; + int slices = 16; + for(int i = 0; i < slices; ++i) + { + float ex1 = sinf(M_PI/2 / slices * i) * w; + float ey1 = cosf(M_PI/2 / slices * i) * h; - glBegin(GL_TRIANGLES); + float ex2 = sinf(M_PI/2 / slices * (i+1)) * w; + float ey2 = cosf(M_PI/2 / slices * (i+1)) * h; - // Bottom/Right - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT); - glVertex2f(x + ex1, y + ey1); - glVertex2f(x + ex2, y + ey2); + glBegin(GL_TRIANGLES); - // Top/Left - glVertex2f(0, 0); - glVertex2f(x - ex1, y - ey1); - glVertex2f(x - ex2, y - ey2); + // Bottom/Right + glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT); + glVertex2f(x + ex1, y + ey1); + glVertex2f(x + ex2, y + ey2); - // Top/Right - glVertex2f(SCREEN_WIDTH, 0); - glVertex2f(x + ex1, y - ey1); - glVertex2f(x + ex2, y - ey2); + // Top/Left + glVertex2f(0, 0); + glVertex2f(x - ex1, y - ey1); + glVertex2f(x - ex2, y - ey2); - // Bottom/Left - glVertex2f(0, SCREEN_HEIGHT); - glVertex2f(x - ex1, y + ey1); - glVertex2f(x - ex2, y + ey2); + // Top/Right + glVertex2f(SCREEN_WIDTH, 0); + glVertex2f(x + ex1, y - ey1); + glVertex2f(x + ex2, y - ey2); - glEnd(); - } - glEnable(GL_TEXTURE_2D); - glColor4f(1, 1, 1, 1); - } + // Bottom/Left + glVertex2f(0, SCREEN_HEIGHT); + glVertex2f(x - ex1, y + ey1); + glVertex2f(x - ex2, y + ey2); - void - Renderer::do_take_screenshot() - { - // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it? - - SDL_Surface *shot_surf; - // create surface to hold screenshot - #if SDL_BYTEORDER == SDL_BIG_ENDIAN - shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0); - #else - shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0); - #endif - if (!shot_surf) { - log_warning << "Could not create RGB Surface to contain screenshot" << std::endl; - return; + glEnd(); } + glEnable(GL_TEXTURE_2D); + glColor4f(1, 1, 1, 1); +} - // read pixels into array - char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT]; - if (!pixels) { - log_warning << "Could not allocate memory to store screenshot" << std::endl; - SDL_FreeSurface(shot_surf); - return; - } - glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); +void +Renderer::do_take_screenshot() +{ + // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it? + + SDL_Surface *shot_surf; + // create surface to hold screenshot +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0); +#else + shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0); +#endif + if (!shot_surf) { + log_warning << "Could not create RGB Surface to contain screenshot" << std::endl; + return; + } + + // read pixels into array + char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT]; + if (!pixels) { + log_warning << "Could not allocate memory to store screenshot" << std::endl; + SDL_FreeSurface(shot_surf); + return; + } + glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); - // copy array line-by-line - for (int i = 0; i < SCREEN_HEIGHT; i++) { - char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1)); - if(SDL_MUSTLOCK(shot_surf)) + // copy array line-by-line + for (int i = 0; i < SCREEN_HEIGHT; i++) { + char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1)); + if(SDL_MUSTLOCK(shot_surf)) { SDL_LockSurface(shot_surf); } - char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch; - memcpy(dst, src, 3 * SCREEN_WIDTH); - if(SDL_MUSTLOCK(shot_surf)) + char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch; + memcpy(dst, src, 3 * SCREEN_WIDTH); + if(SDL_MUSTLOCK(shot_surf)) { SDL_UnlockSurface(shot_surf); } - } + } - // free array - delete[](pixels); - - // save screenshot - static const std::string writeDir = PHYSFS_getWriteDir(); - static const std::string dirSep = PHYSFS_getDirSeparator(); - static const std::string baseName = "screenshot"; - static const std::string fileExt = ".bmp"; - std::string fullFilename; - for (int num = 0; num < 1000; num++) { - std::ostringstream oss; - oss << baseName; - oss << std::setw(3) << std::setfill('0') << num; - oss << fileExt; - std::string fileName = oss.str(); - fullFilename = writeDir + dirSep + fileName; - if (!PHYSFS_exists(fileName.c_str())) { - SDL_SaveBMP(shot_surf, fullFilename.c_str()); - log_debug << "Wrote screenshot to \"" << fullFilename << "\"" << std::endl; - SDL_FreeSurface(shot_surf); - return; - } + // free array + delete[](pixels); + + // save screenshot + static const std::string writeDir = PHYSFS_getWriteDir(); + static const std::string dirSep = PHYSFS_getDirSeparator(); + static const std::string baseName = "screenshot"; + static const std::string fileExt = ".bmp"; + std::string fullFilename; + for (int num = 0; num < 1000; num++) { + std::ostringstream oss; + oss << baseName; + oss << std::setw(3) << std::setfill('0') << num; + oss << fileExt; + std::string fileName = oss.str(); + fullFilename = writeDir + dirSep + fileName; + if (!PHYSFS_exists(fileName.c_str())) { + SDL_SaveBMP(shot_surf, fullFilename.c_str()); + log_debug << "Wrote screenshot to \"" << fullFilename << "\"" << std::endl; + SDL_FreeSurface(shot_surf); + return; } - log_warning << "Did not save screenshot, because all files up to \"" << fullFilename << "\" already existed" << std::endl; - SDL_FreeSurface(shot_surf); } + log_warning << "Did not save screenshot, because all files up to \"" << fullFilename << "\" already existed" << std::endl; + SDL_FreeSurface(shot_surf); +} - void - Renderer::flip() - { - assert_gl("drawing"); - SDL_GL_SwapBuffers(); - } +void +Renderer::flip() +{ + assert_gl("drawing"); + SDL_GL_SwapBuffers(); +} - void - Renderer::resize(int w, int h) - { - SDL_SetVideoMode(w, h, 0, SDL_OPENGL | SDL_RESIZABLE); - - config->window_width = w; - config->window_height = h; +void +Renderer::resize(int w, int h) +{ + SDL_SetVideoMode(w, h, 0, SDL_OPENGL | SDL_RESIZABLE); - // FIXME: Add aspect handling - SCREEN_WIDTH = w; - SCREEN_HEIGHT = h; + config->window_width = w; + config->window_height = h; - glViewport(0, 0, config->window_width, config->window_height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0); - } + apply_config(); +} + +void +Renderer::apply_config() +{ + std::cout << "Applying Config: " << config->aspect_width << ":" << config->aspect_height << std::endl; + + int w,h; + float target_aspect = float(config->aspect_width) / float(config->aspect_height); + float desktop_aspect = 4.0f / 3.0f; // random default fallback guess + + if (desktop_width != -1 && desktop_height != -1) + { + desktop_aspect = float(desktop_width) / float(desktop_height); + } + + if (config->use_fullscreen) + { + w = config->fullscreen_width; + h = config->fullscreen_height; + desktop_aspect = float(w) / float(h); + } + else + { + w = config->window_width; + h = config->window_height; + } + + std::cout + << " -> " << w << "x" << h << " -> " << target_aspect << " " << desktop_aspect << std::endl; + + if (target_aspect > 1.0f) + { + SCREEN_WIDTH = w * (target_aspect / desktop_aspect); + SCREEN_HEIGHT = h; + } + else + { + SCREEN_WIDTH = w; + SCREEN_HEIGHT = h * (target_aspect / desktop_aspect); + } + + // Limit must take aspect into account + //SCREEN_WIDTH = std::min(w, 1024); + //SCREEN_HEIGHT = std::min(h, 768); + + // Position the Viewport in the center of the window + glViewport(std::max(0, (config->window_width - w)/2), + std::max(0, (config->window_height - h)/2), + w, h); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0); } +} // namespace GL + #endif diff --git a/src/video/gl_renderer.hpp b/src/video/gl_renderer.hpp index a870c5752..dfb08bd21 100644 --- a/src/video/gl_renderer.hpp +++ b/src/video/gl_renderer.hpp @@ -29,6 +29,10 @@ namespace GL { class Renderer : public ::Renderer { + private: + int desktop_width; + int desktop_height; + public: Renderer(); ~Renderer(); @@ -42,6 +46,7 @@ namespace GL void do_take_screenshot(); void flip(); void resize(int w, int h); + void apply_config(); }; } diff --git a/src/video/renderer.hpp b/src/video/renderer.hpp index 7d3868aa8..777eefdb8 100644 --- a/src/video/renderer.hpp +++ b/src/video/renderer.hpp @@ -54,6 +54,7 @@ public: virtual void do_take_screenshot() = 0; virtual void flip() = 0; virtual void resize(int w, int h) = 0; + virtual void apply_config() = 0; static Renderer* instance() { return instance_; } diff --git a/src/video/sdl_renderer.hpp b/src/video/sdl_renderer.hpp index 572c34ee7..fe34d82b6 100644 --- a/src/video/sdl_renderer.hpp +++ b/src/video/sdl_renderer.hpp @@ -40,6 +40,7 @@ namespace SDL void do_take_screenshot(); void flip(); void resize(int w, int h); + void apply_config() {} private: SDL_Surface *screen; int numerator, denominator; -- 2.11.0