// SuperTux
// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
+// Updated by GiBy 2013 for SDL2 <giby_the_kid@yahoo.fr>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
#include <iomanip>
#include <iostream>
#include <physfs.h>
+#include "SDL.h"
#include "supertux/gameconfig.hpp"
#include "supertux/globals.hpp"
#endif
GLRenderer::GLRenderer() :
+ window(),
desktop_size(-1, -1),
screen_size(-1, -1),
- fullscreen_active(false)
+ fullscreen_active(false),
+ last_texture(static_cast<GLuint> (-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_size = Size(info->current_w, info->current_h);
- }
-#endif
+ SDL_DisplayMode mode;
+ SDL_GetCurrentDisplayMode(0, &mode);
+ desktop_size = Size(mode.w, mode.h);
if(texture_manager != 0)
texture_manager->save_textures();
-#ifdef SDL_GL_SWAP_CONTROL
- if(config->try_vsync) {
+ if(g_config->try_vsync) {
/* we want vsync for smooth scrolling */
- SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
+ if (SDL_GL_SetSwapInterval(-1) != 0)
+ {
+ log_info << "no support for late swap tearing vsync: " << SDL_GetError() << std::endl;
+ if (SDL_GL_SetSwapInterval(1))
+ {
+ log_info << "no support for vsync: " << SDL_GetError() << std::endl;
+ }
+ }
}
-#endif
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- // FIXME: 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);
GLRenderer::~GLRenderer()
{
+ SDL_GL_DeleteContext(glcontext);
+ SDL_DestroyWindow(window);
}
void
GLRenderer::draw_surface(const DrawingRequest& request)
{
const Surface* surface = (const Surface*) request.request_data;
- boost::shared_ptr<GLTexture> gltexture = boost::dynamic_pointer_cast<GLTexture>(surface->get_texture());
- GLSurfaceData *surface_data = reinterpret_cast<GLSurfaceData *>(surface->get_surface_data());
+ if(surface == NULL)
+ {
+ return;
+ }
+ GLTexture* gltexture = static_cast<GLTexture*>(surface->get_texture().get());
+ if(gltexture == NULL)
+ {
+ return;
+ }
+ GLSurfaceData *surface_data = static_cast<GLSurfaceData*>(surface->get_surface_data());
+ if(surface_data == NULL)
+ {
+ return;
+ }
- glBindTexture(GL_TEXTURE_2D, gltexture->get_handle());
+ GLuint th = gltexture->get_handle();
+ if (th != last_texture) {
+ last_texture = th;
+ glBindTexture(GL_TEXTURE_2D, th);
+ }
intern_draw(request.pos.x, request.pos.y,
request.pos.x + surface->get_width(),
request.pos.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());
+ GLuint th = gltexture->get_handle();
+ if (th != last_texture) {
+ last_texture = th;
+ glBindTexture(GL_TEXTURE_2D, th);
+ }
intern_draw(request.pos.x, request.pos.y,
request.pos.x + surfacepartrequest->size.x,
request.pos.y + surfacepartrequest->size.y,
float vertices[] = {
0, 0,
- SCREEN_WIDTH, 0,
- SCREEN_WIDTH, SCREEN_HEIGHT,
- 0, SCREEN_HEIGHT
+ float(SCREEN_WIDTH), 0,
+ float(SCREEN_WIDTH), float(SCREEN_HEIGHT),
+ 0, float(SCREEN_HEIGHT)
};
glVertexPointer(2, GL_FLOAT, 0, vertices);
GLRenderer::flip()
{
assert_gl("drawing");
- SDL_GL_SwapBuffers();
+ SDL_GL_SwapWindow(window);
}
void
GLRenderer::resize(int w, int h)
{
- // This causes the screen to go black, which is annoying, but seems
- // unavoidable with SDL at the moment
- SDL_SetVideoMode(w, h, 0, SDL_OPENGL | SDL_RESIZABLE);
-
g_config->window_size = Size(w, h);
+ PHYSICAL_SCREEN_WIDTH = w;
+ PHYSICAL_SCREEN_HEIGHT = h;
+
apply_config();
}
SCREEN_HEIGHT = static_cast<int>(screen_size.height * (target_aspect / desktop_aspect));
}
- Size max_size(1600, 1200); // FIXME: Maybe 1920 is ok too
+ Size max_size(1280, 800);
+ Size min_size(640, 480);
if (g_config->magnification == 0.0f) // Magic value that means 'minfill'
{
// This scales SCREEN_WIDTH/SCREEN_HEIGHT so that they never excede
- // max_size.width/max_size.height
+ // max_size.width/max_size.height resp. min_size.width/min_size.height
if (SCREEN_WIDTH > max_size.width || SCREEN_HEIGHT > max_size.height)
{
float scale1 = float(max_size.width)/SCREEN_WIDTH;
float scale = (scale1 < scale2) ? scale1 : scale2;
SCREEN_WIDTH = static_cast<int>(SCREEN_WIDTH * scale);
SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT * scale);
+ }
+ else if (SCREEN_WIDTH < min_size.width || SCREEN_HEIGHT < min_size.height)
+ {
+ float scale1 = float(min_size.width)/SCREEN_WIDTH;
+ float scale2 = float(min_size.height)/SCREEN_HEIGHT;
+ float scale = (scale1 < scale2) ? scale1 : scale2;
+ SCREEN_WIDTH = static_cast<int>(SCREEN_WIDTH * scale);
+ SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT * scale);
}
+
glViewport(0, 0, screen_size.width, screen_size.height);
}
// Clear both buffers so that we get a clean black border without junk
glClear(GL_COLOR_BUFFER_BIT);
- SDL_GL_SwapBuffers();
+ SDL_GL_SwapWindow(window);
glClear(GL_COLOR_BUFFER_BIT);
- SDL_GL_SwapBuffers();
+ SDL_GL_SwapWindow(window);
glViewport(std::max(0, (screen_size.width - new_size.width) / 2),
std::max(0, (screen_size.height - new_size.height) / 2),
void
GLRenderer::apply_video_mode(const Size& size, bool fullscreen)
{
- // Only change video mode when its different from the current one
- if (screen_size != size || fullscreen_active != fullscreen)
+ if (window)
{
- int flags = SDL_OPENGL;
+ SDL_SetWindowSize(window, size.width, size.height);
if (fullscreen)
{
- flags |= SDL_FULLSCREEN;
+ int fullscreen_flags = SDL_WINDOW_FULLSCREEN; // SDL_WINDOW_FULLSCREEN_DESKTOP or 0
+ SDL_SetWindowDisplayMode(window, NULL);
+
+ SDL_DisplayMode mode;
+ mode.format = SDL_PIXELFORMAT_RGB888;
+ mode.w = g_config->fullscreen_size.width;
+ mode.h = g_config->fullscreen_size.height;
+ mode.refresh_rate = g_config->fullscreen_refresh_rate;
+ mode.driverdata = 0;
+
+ if (SDL_SetWindowDisplayMode(window, &mode) != 0)
+ {
+ log_warning << "failed to set display mode: "
+ << mode.w << "x" << mode.h << "@" << mode.refresh_rate << ": "
+ << SDL_GetError() << std::endl;
+ }
+ else
+ {
+ SDL_SetWindowFullscreen(window, fullscreen_flags);
+ }
}
else
{
- flags |= SDL_RESIZABLE;
- }
-
- if (SDL_Surface *screen = SDL_SetVideoMode(size.width, size.height, 0, flags))
- {
- screen_size = Size(screen->w, screen->h);
- fullscreen_active = fullscreen;
+ SDL_SetWindowFullscreen(window, 0);
}
- else
+ }
+ else
+ {
+ // Only change video mode when its different from the current one
+ if (screen_size != size || fullscreen_active != fullscreen)
{
- std::ostringstream msg;
- msg << "Couldn't set video mode " << size.width << "x" << size.height << ": " << SDL_GetError();
- throw std::runtime_error(msg.str());
+ int flags = SDL_WINDOW_OPENGL;
+
+ if (fullscreen)
+ {
+ flags |= SDL_WINDOW_FULLSCREEN;
+ }
+ else
+ {
+ flags |= SDL_WINDOW_RESIZABLE;
+ }
+
+ window = SDL_CreateWindow("SuperTux",
+ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ size.width, size.height,
+ flags);
+ if (!window)
+ {
+ std::ostringstream msg;
+ msg << "Couldn't set video mode " << size.width << "x" << size.height << ": " << SDL_GetError();
+ throw std::runtime_error(msg.str());
+ }
+ else
+ {
+ glcontext = SDL_GL_CreateContext(window);
+ screen_size = size;
+
+ PHYSICAL_SCREEN_WIDTH = size.width;
+ PHYSICAL_SCREEN_HEIGHT = size.height;
+
+ SCREEN_WIDTH = size.width;
+ SCREEN_HEIGHT = size.height;
+
+ fullscreen_active = fullscreen;
+ }
}
}
}
+void
+GLRenderer::set_gamma(float gamma)
+{
+ Uint16 ramp[256];
+ SDL_CalculateGammaRamp(gamma, ramp);
+ SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
+}
+
/* EOF */