Merge branch 'master' of https://code.google.com/p/supertux
authorMathnerd314 <mathnerd314.gph+hs@gmail.com>
Sun, 3 Aug 2014 18:29:32 +0000 (20:29 +0200)
committerMathnerd314 <mathnerd314.gph+hs@gmail.com>
Sun, 3 Aug 2014 18:29:32 +0000 (20:29 +0200)
Conflicts:
src/supertux/main.cpp

Modified CMakeLists.txt to actually build properly

71 files changed:
.gitignore
CMakeLists.txt
data/images/engine/fonts/greek/Shadow-small.png [new file with mode: 0644]
data/images/powerups/egg/egg-0.png [new file with mode: 0644]
data/images/powerups/egg/egg-1.png [new file with mode: 0644]
data/images/powerups/egg/egg-10.png [new file with mode: 0644]
data/images/powerups/egg/egg-11.png [new file with mode: 0644]
data/images/powerups/egg/egg-12.png [new file with mode: 0644]
data/images/powerups/egg/egg-13.png [new file with mode: 0644]
data/images/powerups/egg/egg-14.png [new file with mode: 0644]
data/images/powerups/egg/egg-15.png [new file with mode: 0644]
data/images/powerups/egg/egg-16.png [new file with mode: 0644]
data/images/powerups/egg/egg-17.png [new file with mode: 0644]
data/images/powerups/egg/egg-18.png [new file with mode: 0644]
data/images/powerups/egg/egg-19.png [new file with mode: 0644]
data/images/powerups/egg/egg-2.png [new file with mode: 0644]
data/images/powerups/egg/egg-3.png [new file with mode: 0644]
data/images/powerups/egg/egg-4.png [new file with mode: 0644]
data/images/powerups/egg/egg-5.png [new file with mode: 0644]
data/images/powerups/egg/egg-6.png [new file with mode: 0644]
data/images/powerups/egg/egg-7.png [new file with mode: 0644]
data/images/powerups/egg/egg-8.png [new file with mode: 0644]
data/images/powerups/egg/egg-9.png [new file with mode: 0644]
data/images/powerups/egg/egg.png [deleted file]
src/control/joystickkeyboardcontroller.cpp
src/control/joystickkeyboardcontroller.hpp
src/gui/button.cpp [deleted file]
src/gui/button.hpp [deleted file]
src/gui/button_group.cpp [deleted file]
src/gui/button_group.hpp [deleted file]
src/gui/menu.cpp
src/gui/menu_item.cpp
src/gui/mousecursor.cpp
src/main.cpp
src/object/explosion.cpp
src/object/growup.cpp
src/physfs/physfs_sdl.cpp
src/scripting/functions.cpp
src/supertux/console.cpp
src/supertux/gameconfig.cpp
src/supertux/gameconfig.hpp
src/supertux/globals.cpp
src/supertux/globals.hpp
src/supertux/level.cpp
src/supertux/main.cpp
src/supertux/menu/joystick_menu.cpp
src/supertux/menu/keyboard_menu.cpp
src/supertux/menu/keyboard_menu.hpp
src/supertux/menu/options_menu.cpp
src/supertux/screen_manager.cpp
src/video/drawing_context.cpp
src/video/drawing_context.hpp
src/video/font.cpp
src/video/gl/gl_lightmap.cpp
src/video/gl/gl_lightmap.hpp
src/video/gl/gl_renderer.cpp
src/video/gl/gl_renderer.hpp
src/video/gl/gl_texture.cpp
src/video/renderer.hpp
src/video/sdl/sdl_lightmap.cpp
src/video/sdl/sdl_lightmap.hpp
src/video/sdl/sdl_painter.cpp [new file with mode: 0644]
src/video/sdl/sdl_painter.hpp [new file with mode: 0644]
src/video/sdl/sdl_renderer.cpp
src/video/sdl/sdl_renderer.hpp
src/video/sdl/sdl_texture.cpp
src/video/sdl/sdl_texture.hpp
src/video/texture_manager.cpp
src/video/util.cpp [new file with mode: 0644]
src/video/util.hpp [new file with mode: 0644]
src/worldmap/worldmap.cpp

index 04a59bc..e5de41d 100644 (file)
@@ -21,4 +21,5 @@ data/levels/more/
 .Trashes
 ehthumbs.db
 Thumbs.db
-.directory
\ No newline at end of file
+.directory
+*~
index d423390..5e82c27 100644 (file)
@@ -66,12 +66,13 @@ FIND_PACKAGE(Boost REQUIRED)
 INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIR})
 LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
 
-FIND_PACKAGE(SDL REQUIRED)
-INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR})
-SET(HAVE_SDL TRUE)
+INCLUDE(FindPkgConfig)
+PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
+INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS})
 
-FIND_PACKAGE(SDL_image REQUIRED)
-INCLUDE_DIRECTORIES(${SDLIMAGE_INCLUDE_DIR})
+PKG_SEARCH_MODULE(SDL2IMAGE REQUIRED SDL2_image>=2.0.0)
+INCLUDE_DIRECTORIES(${SDL2IMAGE_INCLUDE_DIRS})
+SET(HAVE_SDL TRUE)
 
 OPTION(ENABLE_OPENGL "Enable OpenGL support" ON)
 IF(ENABLE_OPENGL)
@@ -234,7 +235,7 @@ IF(CMAKE_COMPILER_IS_GNUCC)
   SET(CMAKE_CXX_FLAGS_PROFILE "-pg" CACHE STRING "Profile flags")
   SET(CMAKE_C_FLAGS_PROFILE "-pg" CACHE STRING "Profile flags")
   SET(CMAKE_LD_FLAGS_PROFILE "-lgmon" CACHE STRING "Profile flags")
-  ADD_DEFINITIONS(-Wall -Wextra -funit-at-a-time)
+  ADD_DEFINITIONS(-Wall -Wextra -Wno-unused-parameter -funit-at-a-time)
   IF(WERROR)
     ADD_DEFINITIONS(-Werror)
   ELSE(WERROR)
@@ -342,8 +343,8 @@ ADD_DEPENDENCIES(supertux2 gitversion)
 ## Link supertux binary with squirrel and other libraries
 
 TARGET_LINK_LIBRARIES(supertux2 squirrel)
-TARGET_LINK_LIBRARIES(supertux2 ${SDL_LIBRARY})
-TARGET_LINK_LIBRARIES(supertux2 ${SDLIMAGE_LIBRARY})
+TARGET_LINK_LIBRARIES(supertux2 ${SDL2_LIBRARIES})
+TARGET_LINK_LIBRARIES(supertux2 ${SDL2IMAGE_LIBRARIES})
 TARGET_LINK_LIBRARIES(supertux2 ${OPENAL_LIBRARY})
 TARGET_LINK_LIBRARIES(supertux2 ${OGGVORBIS_LIBRARIES})
 TARGET_LINK_LIBRARIES(supertux2 ${PHYSFS_LIBRARY})
diff --git a/data/images/engine/fonts/greek/Shadow-small.png b/data/images/engine/fonts/greek/Shadow-small.png
new file mode 100644 (file)
index 0000000..7f2720a
Binary files /dev/null and b/data/images/engine/fonts/greek/Shadow-small.png differ
diff --git a/data/images/powerups/egg/egg-0.png b/data/images/powerups/egg/egg-0.png
new file mode 100644 (file)
index 0000000..8d6105f
Binary files /dev/null and b/data/images/powerups/egg/egg-0.png differ
diff --git a/data/images/powerups/egg/egg-1.png b/data/images/powerups/egg/egg-1.png
new file mode 100644 (file)
index 0000000..863b78b
Binary files /dev/null and b/data/images/powerups/egg/egg-1.png differ
diff --git a/data/images/powerups/egg/egg-10.png b/data/images/powerups/egg/egg-10.png
new file mode 100644 (file)
index 0000000..cb804d7
Binary files /dev/null and b/data/images/powerups/egg/egg-10.png differ
diff --git a/data/images/powerups/egg/egg-11.png b/data/images/powerups/egg/egg-11.png
new file mode 100644 (file)
index 0000000..9e326b2
Binary files /dev/null and b/data/images/powerups/egg/egg-11.png differ
diff --git a/data/images/powerups/egg/egg-12.png b/data/images/powerups/egg/egg-12.png
new file mode 100644 (file)
index 0000000..1ee1f18
Binary files /dev/null and b/data/images/powerups/egg/egg-12.png differ
diff --git a/data/images/powerups/egg/egg-13.png b/data/images/powerups/egg/egg-13.png
new file mode 100644 (file)
index 0000000..2b5e0a5
Binary files /dev/null and b/data/images/powerups/egg/egg-13.png differ
diff --git a/data/images/powerups/egg/egg-14.png b/data/images/powerups/egg/egg-14.png
new file mode 100644 (file)
index 0000000..707fc97
Binary files /dev/null and b/data/images/powerups/egg/egg-14.png differ
diff --git a/data/images/powerups/egg/egg-15.png b/data/images/powerups/egg/egg-15.png
new file mode 100644 (file)
index 0000000..37266c8
Binary files /dev/null and b/data/images/powerups/egg/egg-15.png differ
diff --git a/data/images/powerups/egg/egg-16.png b/data/images/powerups/egg/egg-16.png
new file mode 100644 (file)
index 0000000..9e24d1c
Binary files /dev/null and b/data/images/powerups/egg/egg-16.png differ
diff --git a/data/images/powerups/egg/egg-17.png b/data/images/powerups/egg/egg-17.png
new file mode 100644 (file)
index 0000000..a6193d4
Binary files /dev/null and b/data/images/powerups/egg/egg-17.png differ
diff --git a/data/images/powerups/egg/egg-18.png b/data/images/powerups/egg/egg-18.png
new file mode 100644 (file)
index 0000000..e064139
Binary files /dev/null and b/data/images/powerups/egg/egg-18.png differ
diff --git a/data/images/powerups/egg/egg-19.png b/data/images/powerups/egg/egg-19.png
new file mode 100644 (file)
index 0000000..cd2e385
Binary files /dev/null and b/data/images/powerups/egg/egg-19.png differ
diff --git a/data/images/powerups/egg/egg-2.png b/data/images/powerups/egg/egg-2.png
new file mode 100644 (file)
index 0000000..ed6b220
Binary files /dev/null and b/data/images/powerups/egg/egg-2.png differ
diff --git a/data/images/powerups/egg/egg-3.png b/data/images/powerups/egg/egg-3.png
new file mode 100644 (file)
index 0000000..e0f4bbb
Binary files /dev/null and b/data/images/powerups/egg/egg-3.png differ
diff --git a/data/images/powerups/egg/egg-4.png b/data/images/powerups/egg/egg-4.png
new file mode 100644 (file)
index 0000000..e041ad7
Binary files /dev/null and b/data/images/powerups/egg/egg-4.png differ
diff --git a/data/images/powerups/egg/egg-5.png b/data/images/powerups/egg/egg-5.png
new file mode 100644 (file)
index 0000000..0fc79ce
Binary files /dev/null and b/data/images/powerups/egg/egg-5.png differ
diff --git a/data/images/powerups/egg/egg-6.png b/data/images/powerups/egg/egg-6.png
new file mode 100644 (file)
index 0000000..fd2bfb3
Binary files /dev/null and b/data/images/powerups/egg/egg-6.png differ
diff --git a/data/images/powerups/egg/egg-7.png b/data/images/powerups/egg/egg-7.png
new file mode 100644 (file)
index 0000000..d9426ab
Binary files /dev/null and b/data/images/powerups/egg/egg-7.png differ
diff --git a/data/images/powerups/egg/egg-8.png b/data/images/powerups/egg/egg-8.png
new file mode 100644 (file)
index 0000000..9a7fc19
Binary files /dev/null and b/data/images/powerups/egg/egg-8.png differ
diff --git a/data/images/powerups/egg/egg-9.png b/data/images/powerups/egg/egg-9.png
new file mode 100644 (file)
index 0000000..ff38eaf
Binary files /dev/null and b/data/images/powerups/egg/egg-9.png differ
diff --git a/data/images/powerups/egg/egg.png b/data/images/powerups/egg/egg.png
deleted file mode 100644 (file)
index 8d6105f..0000000
Binary files a/data/images/powerups/egg/egg.png and /dev/null differ
index aa05152..0e176e2 100644 (file)
@@ -28,6 +28,7 @@
 #include "supertux/menu/keyboard_menu.hpp"
 #include "util/gettext.hpp"
 #include "util/writer.hpp"
+//#include <SDL_keycode.h> // add by giby
 
 JoystickKeyboardController::JoystickKeyboardController() :
   controller(),
@@ -138,12 +139,12 @@ JoystickKeyboardController::updateAvailableJoysticks()
       SDL_Joystick* joystick = SDL_JoystickOpen(i);
       bool good = true;
       if(SDL_JoystickNumButtons(joystick) < 2) {
-        log_info << "Joystick " << i << ": " << SDL_JoystickName(i) << " has less than 2 buttons" << std::endl;
+        log_info << _("Joystick ") << i << ": " << SDL_JoystickID(i) << _(" has less than 2 buttons") << std::endl;
         good = false;
       }
       if(SDL_JoystickNumAxes(joystick) < 2
          && SDL_JoystickNumHats(joystick) == 0) {
-        log_info << "Joystick " << i << ": " << SDL_JoystickName(i) << " has less than 2 axes and no hat" << std::endl;
+        log_info << _("Joystick ") << i << ": " << SDL_JoystickID(i) << _(" has less than 2 axes and no hat") << std::endl;
         good = false;
       }
       if(!good) {
@@ -196,10 +197,10 @@ JoystickKeyboardController::read(const Reader& lisp)
         const lisp::Lisp* map = iter.lisp();
         map->get("key", key);
         map->get("control", control);
-        if(key < SDLK_FIRST || key >= SDLK_LAST) {
-          log_info << "Invalid key '" << key << "' in keymap" << std::endl;
-          continue;
-        }
+//        if(key < SDLK_FIRST || key >= SDLK_LAST) {
+//          log_info << "Invalid key '" << key << "' in keymap" << std::endl;
+//          continue;
+//        }
 
         int i = 0;
         for(i = 0; Controller::controlNames[i] != 0; ++i) {
@@ -210,18 +211,18 @@ JoystickKeyboardController::read(const Reader& lisp)
           log_info << "Invalid control '" << control << "' in keymap" << std::endl;
           continue;
         }
-        keymap[SDLKey(key)] = Control(i);
+        keymap[SDL_Keycode(key)] = Control(i);
       }
     }
   }
 
-  const lisp::Lisp* joystick_lisp = lisp.get_lisp("joystick");
+  const lisp::Lisp* joystick_lisp = lisp.get_lisp(_("joystick"));
   if(joystick_lisp) {
     joystick_lisp->get("dead-zone", dead_zone);
     joystick_lisp->get("jump-with-up", jump_with_up_joy);
     lisp::ListIterator iter(joystick_lisp);
     while(iter.next()) {
-      if(iter.item() == "map") {
+      if(iter.item() == _("map")) {
         int button = -1;
         int axis   = 0;
         int hat    = -1;
@@ -341,6 +342,10 @@ void
 JoystickKeyboardController::process_event(const SDL_Event& event)
 {
   switch(event.type) {
+    case SDL_TEXTINPUT:
+      process_text_input_event(event.text);
+      break;
+
     case SDL_KEYUP:
     case SDL_KEYDOWN:
       process_key_event(event.key);
@@ -489,6 +494,17 @@ JoystickKeyboardController::process_hat_event(const SDL_JoyHatEvent& jhat)
 }
 
 void
+JoystickKeyboardController::process_text_input_event(const SDL_TextInputEvent& event)
+{
+  if (Console::instance->hasFocus()) {
+    for(int i = 0; event.text[i] != '\0'; ++i)
+    {
+      Console::instance->input(event.text[i]);
+    }
+  }
+}
+
+void
 JoystickKeyboardController::process_key_event(const SDL_KeyboardEvent& event)
 {
   KeyMap::iterator key_mapping = keymap.find(event.keysym.sym);
@@ -506,7 +522,7 @@ JoystickKeyboardController::process_key_event(const SDL_KeyboardEvent& event)
       process_menu_key_event(event);
     } else if(key_mapping == keymap.end()) {
       // default action: update controls
-      //log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl;
+      //log_debug << "Key " << event.key.SDL_Keycode.sym << " is unbound" << std::endl;
     } else {
       Control control = key_mapping->second;
       bool value = (event.type == SDL_KEYDOWN);
@@ -558,10 +574,6 @@ JoystickKeyboardController::process_console_key_event(const SDL_KeyboardEvent& e
       Console::instance->move_cursor(+1);
       break;
     default:
-      int c = event.keysym.unicode;
-      if ((c >= 32) && (c <= 126)) {
-        Console::instance->input((char)c);
-      }
       break;
   }
 }
@@ -685,7 +697,7 @@ JoystickKeyboardController::bind_joybutton(JoyId joy_id, int button, Control con
 }
 
 void
-JoystickKeyboardController::bind_key(SDLKey key, Control control)
+JoystickKeyboardController::bind_key(SDL_Keycode key, Control control)
 {
   // remove all previous mappings for that control and for that key
   for(KeyMap::iterator i = keymap.begin();
@@ -710,7 +722,7 @@ JoystickKeyboardController::bind_key(SDLKey key, Control control)
 void
 JoystickKeyboardController::print_joystick_mappings()
 {
-  std::cout << "Joystick Mappings" << std::endl;
+  std::cout << _("Joystick Mappings") << std::endl;
   std::cout << "-----------------" << std::endl;
   for(AxisMap::iterator i = joy_axis_map.begin(); i != joy_axis_map.end(); ++i) {
     std::cout << "Axis: " << i->first.second << " -> " << i->second << std::endl;
@@ -726,7 +738,7 @@ JoystickKeyboardController::print_joystick_mappings()
   std::cout << std::endl;
 }
 
-SDLKey
+SDL_Keycode
 JoystickKeyboardController::reversemap_key(Control c)
 {
   for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {
index 00c4c2f..705b7bc 100644 (file)
@@ -20,7 +20,7 @@
 #include "control/controller.hpp"
 
 #include <SDL.h>
-
+#include <SDL_keycode.h> // add by giby
 #include <map>
 #include <string>
 #include <vector>
@@ -33,7 +33,9 @@ class KeyboardMenu;
 class JoystickMenu;
 class Controller;
 
-class JoystickKeyboardController
+    //SDL_JoystickID myID = SDL_JoystickInstanceID(myOpenedStick);
+
+class JoystickKeyboardController // http://wiki.libsdl.org/moin.fcg/SDL_Joystick for info 
 {
 private:
   friend class KeyboardMenu;
@@ -42,7 +44,7 @@ private:
   typedef Controller::Control Control;
   typedef Uint8 JoyId;
 
-  typedef std::map<SDLKey, Control> KeyMap;
+  typedef std::map<SDL_Keycode, Control> KeyMap;
   typedef std::map<std::pair<JoyId, int>, Control> ButtonMap;
   typedef std::map<std::pair<JoyId, int>, Control> AxisMap;
   typedef std::map<std::pair<JoyId, int>, Control> HatMap;
@@ -65,6 +67,7 @@ public:
   Controller *get_main_controller();
 
 private:
+  void process_text_input_event(const SDL_TextInputEvent& event);
   void process_key_event(const SDL_KeyboardEvent& event);
   void process_hat_event(const SDL_JoyHatEvent& jhat);
   void process_axis_event(const SDL_JoyAxisEvent& jaxis);
@@ -74,7 +77,7 @@ private:
 
   void print_joystick_mappings();
 
-  SDLKey reversemap_key(Control c);
+  SDL_Keycode reversemap_key(Control c);
   int    reversemap_joybutton(Control c);
   int    reversemap_joyaxis(Control c);
   int    reversemap_joyhat(Control c);
@@ -84,9 +87,9 @@ private:
   void bind_joybutton(JoyId joy_id, int button, Control c);
   void bind_joyaxis(JoyId joy_id, int axis, Control c);
   void bind_joyhat(JoyId joy_id, int dir, Control c);
-  void bind_key(SDLKey key, Control c);
+  void bind_key(SDL_Keycode key, Control c);
 
-  void set_joy_controls(Control id, bool value);
+  void set_joy_controls(Control id, bool value); 
 
 private:
   Controller *controller;
diff --git a/src/gui/button.cpp b/src/gui/button.cpp
deleted file mode 100644 (file)
index 587b1e3..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-//  SuperTux
-//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
-//
-//  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
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-#include "gui/button.hpp"
-
-#include "supertux/globals.hpp"
-#include "video/drawing_context.hpp"
-
-FontPtr Button::info_font;
-
-Button::Button(SurfacePtr image_, std::string info_, SDLKey binding_) :
-  pos(),
-  size(),
-  image(),
-  binding(binding_),
-  id(),
-  state(),
-  info()
-{
-  image = image_;
-  size = Vector(image->get_width(), image->get_height());
-  id = 0;
-  info = info_;
-}
-
-Button::Button(const Button& rhs) :
-  pos(rhs.pos),
-  size(rhs.size),
-  image(rhs.image),
-  binding(rhs.binding),
-  id(rhs.id),
-  state(rhs.state),
-  info(rhs.info)
-{
-}
-
-Button::~Button()
-{
-}
-
-Button&
-Button::operator=(const Button& rhs)
-{
-  if (this != &rhs)
-  {
-    pos = rhs.pos;
-    size = rhs.size;
-    image = rhs.image;
-    binding = rhs.binding;
-    id = rhs.id;
-    state = rhs.state;
-    info = rhs.info;
-  }
-  return *this;
-}
-
-void Button::draw(DrawingContext &context, bool selected)
-{
-  if(selected)
-    context.draw_filled_rect(pos, size, Color (200,240,220), LAYER_GUI);
-  else
-    context.draw_filled_rect(pos, size, Color (200,200,220), LAYER_GUI);
-
-  Vector tanslation = -context.get_translation();
-  if(state == BT_SHOW_INFO)
-  {
-    Vector offset;
-    if(pos.x + tanslation.x < 100 && pos.y + tanslation.y > SCREEN_HEIGHT - 20)
-      offset = Vector(size.x, - 10);
-    else if(pos.x + tanslation.x < 100)
-      offset = Vector(size.x, 0);
-    else
-      offset = Vector(-30, -size.y/2);
-    context.draw_text(info_font, info, pos + offset, ALIGN_LEFT, LAYER_GUI+2);
-    if(binding != 0)
-      context.draw_text(info_font, "(" + std::string(SDL_GetKeyName(binding)) +
-                        ")", pos + offset + Vector(0,12),
-                        ALIGN_LEFT,  LAYER_GUI+2);
-  }
-
-  context.draw_surface_part(image, Vector(0,0), size, pos, LAYER_GUI+1);
-}
-
-int Button::event(SDL_Event &event, int x_offset, int y_offset)
-{
-  state = BT_NONE;
-  switch(event.type)
-  {
-    case SDL_MOUSEBUTTONDOWN:
-      if(event.button.x > pos.x + x_offset && event.button.x < pos.x + x_offset + size.x &&
-         event.button.y > pos.y + y_offset && event.button.y < pos.y + y_offset + size.y)
-      {
-        if(event.button.button == SDL_BUTTON_RIGHT)
-          state = BT_SHOW_INFO;
-      }
-      break;
-    case SDL_MOUSEBUTTONUP:
-      if(event.button.x > pos.x + x_offset && event.button.x < pos.x + x_offset + size.x &&
-         event.button.y > pos.y + y_offset && event.button.y < pos.y + y_offset + size.y)
-      {
-        if(event.button.button == SDL_BUTTON_LEFT)
-          state = BT_SELECTED;
-      }
-      break;
-    case SDL_KEYDOWN:        // key pressed
-      if(event.key.keysym.sym == binding)
-        state = BT_SELECTED;
-      break;
-    default:
-      break;
-  }
-  return state;
-}
-
-/* EOF */
diff --git a/src/gui/button.hpp b/src/gui/button.hpp
deleted file mode 100644 (file)
index aeeb71c..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-//  SuperTux
-//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
-//
-//  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
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef HEADER_SUPERTUX_GUI_BUTTON_HPP
-#define HEADER_SUPERTUX_GUI_BUTTON_HPP
-
-#include <SDL.h>
-#include <string>
-
-#include "math/vector.hpp"
-#include "video/font_ptr.hpp"
-#include "video/surface_ptr.hpp"
-
-class DrawingContext;
-class Font;
-class ButtonGroup;
-
-enum {
-  BT_NONE,
-  BT_HOVER,
-  BT_SELECTED,
-  BT_SHOW_INFO
-};
-
-class Button
-{
-public:
-  Button(SurfacePtr image_, std::string info_, SDLKey binding_);
-  Button(const Button& rhs);
-  ~Button();
-
-  Button& operator=(const Button& rhs);
-
-  void draw(DrawingContext& context, bool selected);
-  int event(SDL_Event& event, int x_offset = 0, int y_offset = 0);
-
-  static FontPtr info_font;
-
-private:
-  friend class ButtonGroup;
-
-private:
-  Vector pos;
-  Vector size;
-
-  SurfacePtr image;
-  SDLKey binding;
-
-  int id;
-  int state;
-  std::string info;
-};
-
-#endif
-
-/* EOF */
diff --git a/src/gui/button_group.cpp b/src/gui/button_group.cpp
deleted file mode 100644 (file)
index 0a2c7ed..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-//  SuperTux
-//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
-//
-//  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
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-#include "gui/button_group.hpp"
-
-#include "supertux/globals.hpp"
-#include "video/drawing_context.hpp"
-
-ButtonGroup::ButtonGroup(Vector pos_, Vector buttons_size_, Vector buttons_box_) :
-  pos(pos_), 
-  buttons_size(buttons_size_), 
-  buttons_box(buttons_box_),
-  buttons(),
-  button_selected(),
-  row(),
-  mouse_hover(),
-  mouse_left_button(),
-  buttons_pair_nb()
-{
-  buttons.clear();
-  row = 0;
-  button_selected = -1;
-  mouse_hover = false;
-  mouse_left_button = false;
-  buttons_pair_nb = 0;
-}
-
-ButtonGroup::~ButtonGroup()
-{
-}
-
-void
-ButtonGroup::add_button(Button button, int id, bool select)
-{
-  button.pos.x = ((buttons.size()-buttons_pair_nb) % (int)buttons_box.x) * buttons_size.x;
-  button.pos.y = ((int)((buttons.size()-buttons_pair_nb) / buttons_box.x)) * buttons_size.y;
-  button.size = buttons_size;
-  button.id = id;
-  if(select)
-    button_selected = id;
-
-  buttons.push_back(button);
-}
-
-void
-ButtonGroup::add_pair_of_buttons(Button button1, int id1, Button button2, int id2)
-{
-  button1.pos.x = button2.pos.x = ((buttons.size()-buttons_pair_nb) % (int)buttons_box.x) * buttons_size.x;
-  button1.pos.y = button2.pos.y = ((int)((buttons.size()-buttons_pair_nb) / buttons_box.x)) * buttons_size.y;
-  button1.size.x = button2.size.x = buttons_size.x;
-  button1.size.y = button2.size.y = buttons_size.y / 2;
-  button2.pos.y += buttons_size.y / 2;
-  button1.id = id1;
-  button2.id = id2;
-
-  buttons_pair_nb++;
-  buttons.push_back(button1);
-  buttons.push_back(button2);
-}
-
-void
-ButtonGroup::draw(DrawingContext &context)
-{
-  context.draw_filled_rect(pos - Vector(12,4),
-                           Vector(buttons_size.x*buttons_box.x + 16, buttons_size.y*buttons_box.y + 8),
-                           Color (0,0,0, 128), LAYER_GUI-1);
-
-  context.push_transform();
-  context.set_translation(Vector(-pos.x, -pos.y + buttons_size.y*row));
-  for(Buttons::iterator i = buttons.begin(); i != buttons.end(); ++i)
-  {
-    if(i->pos.y < row*buttons_size.y ||
-       i->pos.y + i->size.y > (row + buttons_box.y) * buttons_size.y)
-      continue;
-
-    i->draw(context, i->id == button_selected);
-  }
-  context.pop_transform();
-}
-
-bool
-ButtonGroup::event(SDL_Event &event)
-{
-  bool caught_event = false;
-
-  switch(event.type)
-  {
-    case SDL_MOUSEMOTION:
-      mouse_hover = false;
-
-      if(mouse_left_button)
-      {
-        pos.x += int(event.motion.xrel * float(SCREEN_WIDTH)/g_screen->w);
-        pos.y += int(event.motion.yrel * float(SCREEN_HEIGHT)/g_screen->h);
-        caught_event = true;
-      }
-      if(event.button.x > pos.x-12 && event.button.x < pos.x+16 + buttons_box.x*buttons_size.x &&
-         event.button.y > pos.y-4 && event.button.y < pos.y+8 + buttons_box.y*buttons_size.y)
-        mouse_hover = true;
-      break;
-    case SDL_MOUSEBUTTONDOWN:
-      if(event.button.x < pos.x-12 || event.button.x > pos.x+16 +
-         buttons_box.x*buttons_size.x || event.button.y < pos.y-4 ||
-         event.button.y > pos.y+8 + buttons_box.y*buttons_size.y)
-        break;
-
-      caught_event = true;
-
-      if(event.button.button == SDL_BUTTON_WHEELUP)
-      {
-        row--;
-        if(row < 0)
-          row = 0;
-      }
-      else if(event.button.button == SDL_BUTTON_WHEELDOWN)
-      {
-        row++;
-        if(row > (int)((buttons.size()-buttons_pair_nb)/buttons_box.x) - (int)buttons_box.y +
-           ((int)(buttons.size()-buttons_pair_nb)%(int)buttons_box.x != 0 ? 1 : 0))
-          row = (int)((buttons.size()-buttons_pair_nb)/buttons_box.x) - (int)buttons_box.y +
-            ((int)(buttons.size()-buttons_pair_nb)%(int)buttons_box.x != 0 ? 1 : 0);
-      }
-      else if(event.button.button == SDL_BUTTON_LEFT)
-        mouse_left_button = true;
-      else
-        caught_event = false;
-      break;
-    case SDL_MOUSEBUTTONUP:
-      mouse_left_button = false;
-      break;
-    default:
-      break;
-  }
-
-  if(caught_event)
-    return true;
-
-  for(Buttons::iterator i = buttons.begin(); i != buttons.end(); ++i)
-  {
-    if(i->pos.y < row*buttons_size.y ||
-       i->pos.y + i->size.y > (row + buttons_box.y) * buttons_size.y)
-      continue;
-
-    if(i->event(event, (int)pos.x,
-                (int)pos.y - row*(int)buttons_size.y) == BT_SELECTED)
-    {
-      button_selected = i->id;
-      caught_event = true;
-      break;
-    }
-  }
-
-  return caught_event;
-}
-
-int
-ButtonGroup::selected_id()
-{
-  return button_selected;
-}
-
-void
-ButtonGroup::set_unselected()
-{
-  button_selected = -1;
-}
-
-bool
-ButtonGroup::is_hover()
-{
-  return mouse_hover;
-}
-
-/* EOF */
diff --git a/src/gui/button_group.hpp b/src/gui/button_group.hpp
deleted file mode 100644 (file)
index 5c52fb5..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-//  SuperTux
-//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
-//
-//  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
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef HEADER_SUPERTUX_GUI_BUTTON_GROUP_HPP
-#define HEADER_SUPERTUX_GUI_BUTTON_GROUP_HPP
-
-#include <SDL.h>
-#include <string>
-#include <vector>
-
-#include "math/vector.hpp"
-#include "gui/button.hpp"
-
-class DrawingContext;
-
-class ButtonGroup
-{
-public:
-  ButtonGroup(Vector pos_, Vector size_, Vector button_box_);
-  ~ButtonGroup();
-
-  void draw(DrawingContext& context);
-  bool event(SDL_Event& event);
-
-  void add_button(Button button, int id, bool select = false);
-  void add_pair_of_buttons(Button button1, int id1, Button button2, int id2);
-
-  int selected_id();
-  void set_unselected();
-  bool is_hover();
-
-private:
-  typedef std::vector <Button> Buttons;
-
-  Vector pos;
-  Vector buttons_size;
-  Vector buttons_box;
-  Buttons buttons;
-
-  int button_selected;
-  int row;
-  bool mouse_hover;
-  bool mouse_left_button;
-
-  int buttons_pair_nb;
-
-private:
-  ButtonGroup(const ButtonGroup&);
-  ButtonGroup& operator=(const ButtonGroup&);
-};
-
-#endif
-
-/* EOF */
index 2c6f81c..e3fce4b 100644 (file)
@@ -30,6 +30,7 @@
 #include "util/gettext.hpp"
 #include "video/drawing_context.hpp"
 #include "video/font.hpp"
+#include "video/renderer.hpp"
 
 static const float MENU_REPEAT_INITIAL = 0.4f;
 static const float MENU_REPEAT_RATE    = 0.1f;
@@ -770,8 +771,9 @@ Menu::event(const SDL_Event& event)
     case SDL_MOUSEBUTTONDOWN:
     if(event.button.button == SDL_BUTTON_LEFT)
     {
-      int x = int(event.motion.x * float(SCREEN_WIDTH)/g_screen->w);
-      int y = int(event.motion.y * float(SCREEN_HEIGHT)/g_screen->h);
+      Vector mouse_pos = Renderer::instance()->to_logical(event.motion.x, event.motion.y);
+      int x = int(mouse_pos.x);
+      int y = int(mouse_pos.y);
 
       if(x > pos.x - get_width()/2 &&
          x < pos.x + get_width()/2 &&
@@ -785,8 +787,9 @@ Menu::event(const SDL_Event& event)
 
     case SDL_MOUSEMOTION:
     {
-      float x = event.motion.x * SCREEN_WIDTH/g_screen->w;
-      float y = event.motion.y * SCREEN_HEIGHT/g_screen->h;
+      Vector mouse_pos = Renderer::instance()->to_logical(event.motion.x, event.motion.y);
+      float x = mouse_pos.x;
+      float y = mouse_pos.y;
 
       if(x > pos.x - get_width()/2 &&
          x < pos.x + get_width()/2 &&
index f25a4d7..02eb90c 100644 (file)
@@ -19,6 +19,7 @@
 #include "supertux/resources.hpp"
 #include "supertux/timer.hpp"
 #include "video/font.hpp"
+#include <stdio.h>
 
 static const float FLICK_CURSOR_TIME   = 0.5f;
 
index 5994003..101cf1f 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "supertux/globals.hpp"
 #include "video/drawing_context.hpp"
+#include "video/renderer.hpp"
+#include "video/sdl/sdl_renderer.hpp"
 
 MouseCursor* MouseCursor::current_ = 0;
 
@@ -63,8 +65,10 @@ void MouseCursor::draw(DrawingContext& context)
   int x,y,w,h;
   Uint8 ispressed = SDL_GetMouseState(&x,&y);
 
-  x = int(x * float(SCREEN_WIDTH)/g_screen->w);
-  y = int(y * float(SCREEN_HEIGHT)/g_screen->h);
+  Vector mouse_pos = Renderer::instance()->to_logical(x, y);
+
+  x = int(mouse_pos.x);
+  y = int(mouse_pos.y);
 
   w = (int) cursor->get_width();
   h = (int) (cursor->get_height() / MC_STATES_NB);
index 2b4bd21..9eac977 100644 (file)
@@ -14,7 +14,7 @@
 //  You should have received a copy of the GNU General Public License
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-#include <SDL.h>
+#include "SDL.h"
 
 #include "supertux/main.hpp"
 
index 5a22fa7..b7428c0 100644 (file)
@@ -68,8 +68,7 @@ Explosion::explode()
   set_action(hurt ? "default" : "pop", 1);
   sprite->set_animation_loops(1); //TODO: this is necessary because set_action will not set "loops" when "action" is the default action
   sprite->set_angle(graphicsRandom.randf(0, 360)); // a random rotation on the sprite to make explosions appear more random
-  sound_manager->play(hurt ? "sounds/explosion.wav" : "sounds/firecracker.ogg", get_pos());
-    
+  sound_manager->play(hurt ? "sounds/explosion.wav" : "sounds/firecracker.ogg", get_pos());   
 
 #if 0
   // spawn some particles
index 3ce08de..eaafffe 100644 (file)
@@ -37,6 +37,8 @@ GrowUp::GrowUp(Direction direction) :
   //set light for glow effect
   lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE));
   lightsprite->set_color(Color(0.2f, 0.2f, 0.0f));
+  
+  sprite->set_action((direction == LEFT) ? "left" : "right");
 }
 
 void
@@ -73,8 +75,15 @@ GrowUp::collision_solid(const CollisionHit& hit)
     physic.set_velocity_y(0);
   if(hit.bottom && physic.get_velocity_y() > 0)
     physic.set_velocity_y(0);
-  if(hit.left || hit.right)
+  if(hit.left || hit.right) {
     physic.set_velocity_x(-physic.get_velocity_x());
+    if(hit.left)
+      sprite->set_action("right");
+    else {
+      sprite->set_action("left");
+    }
+
+  }
 }
 
 HitResponse
index 82c7869..277f993 100644 (file)
 #include <sstream>
 #include <stdexcept>
 #include <assert.h>
+#include <stdio.h>
 
 #include "util/log.hpp"
 
-static int funcSeek(struct SDL_RWops* context, int offset, int whence)
+static Sint64 funcSeek(struct SDL_RWops* context, Sint64 offset, int whence)
 {
   PHYSFS_file* file = (PHYSFS_file*) context->hidden.unknown.data1;
   int res;
@@ -50,7 +51,7 @@ static int funcSeek(struct SDL_RWops* context, int offset, int whence)
   return (int) PHYSFS_tell(file);
 }
 
-static int funcRead(struct SDL_RWops* context, void* ptr, int size, int maxnum)
+static size_t  funcRead(struct SDL_RWops* context, void* ptr, size_t  size, size_t  maxnum)
 {
   PHYSFS_file* file = (PHYSFS_file*) context->hidden.unknown.data1;
 
index 5a03f37..ba0fc3f 100644 (file)
@@ -32,6 +32,7 @@
 #include "supertux/tile.hpp"
 #include "supertux/world.hpp"
 #include "util/gettext.hpp"
+#include "video/renderer.hpp"
 #include "worldmap/tux.hpp"
 
 #include "scripting/squirrel_util.hpp"
@@ -271,8 +272,9 @@ void camera()
   log_info << "Camera is at " << Sector::current()->camera->get_translation().x << "," << Sector::current()->camera->get_translation().y << std::endl;
 }
 
-void set_gamma(float gamma) {
-  SDL_SetGamma(gamma, gamma, gamma);
+void set_gamma(float gamma)
+{
+  Renderer::instance()->set_gamma(gamma);
 }
 
 void quit()
index efc5ccd..6e663f5 100644 (file)
@@ -431,7 +431,7 @@ Console::show()
   focused = true;
   height = 256;
   alpha = 1.0;
-  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+//  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // Useless in SDL2 :  if you want to disable repeat, then you need to check if the key was repeated and ignore it.
 }
 
 void
@@ -451,7 +451,7 @@ Console::hide()
   // clear input buffer
   inputBuffer = "";
   inputBufferPosition = 0;
-  SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
// SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
 }
 
 void
index 235198c..0322a9d 100644 (file)
@@ -28,6 +28,7 @@
 Config::Config() :
   profile(1),
   fullscreen_size(800, 600),
+  fullscreen_refresh_rate(0),
   window_size(800, 600),
   aspect_size(0, 0), // auto detect
   magnification(0.0f),
@@ -75,6 +76,7 @@ Config::load()
 
     config_video_lisp->get("fullscreen_width",  fullscreen_size.width);
     config_video_lisp->get("fullscreen_height", fullscreen_size.height);
+    config_video_lisp->get("fullscreen_refresh_rate", fullscreen_refresh_rate);
 
     config_video_lisp->get("window_width",  window_size.width);
     config_video_lisp->get("window_height", window_size.height);
@@ -120,6 +122,7 @@ Config::save()
 
   writer.write("fullscreen_width",  fullscreen_size.width);
   writer.write("fullscreen_height", fullscreen_size.height);
+  writer.write("fullscreen_refresh_rate", fullscreen_refresh_rate);
 
   writer.write("window_width",  window_size.width);
   writer.write("window_height", window_size.height);
index 527241f..5836644 100644 (file)
@@ -34,6 +34,9 @@ public:
   // the width/height to be used to display the game in fullscreen
   Size fullscreen_size;
 
+  // refresh rate for use in fullscreen, 0 for auto
+  int fullscreen_refresh_rate;
+
   /** the width/height of the window managers window */
   Size window_size;
 
index e67c243..207c119 100644 (file)
@@ -17,7 +17,6 @@
 #include "supertux/globals.hpp"
 #include <tinygettext/tinygettext.hpp>
 
-SDL_Surface* g_screen;
 JoystickKeyboardController* g_jk_controller = 0;
 tinygettext::DictionaryManager* dictionary_manager = 0;
 
index 8f21b13..8902619 100644 (file)
@@ -42,8 +42,6 @@ extern int SCREEN_HEIGHT;
 // global variables
 extern JoystickKeyboardController* g_jk_controller;
 
-extern SDL_Surface* g_screen;
-
 extern ScreenManager* g_screen_manager;
 
 extern TextureManager* texture_manager;
index 3ecc6a1..00d3335 100644 (file)
@@ -130,7 +130,6 @@ Level::load(const std::string& filepath)
 
     if (license == "") {
       log_warning << "[" <<  filepath << "] The level author \"" << author << "\" did not specify a license for this level \"" << name << "\". You might not be allowed to share it." << std::endl;
-
     }
   } catch(std::exception& e) {
     std::stringstream msg;
index fc945c2..3cd0912 100644 (file)
 #include <binreloc.h>
 #include <tinygettext/log.hpp>
 #include <boost/format.hpp>
+#include <stdio.h>
 extern "C" {
 #include <findlocale.h>
 }
 
+#include "video/renderer.hpp"
 #include "supertux/main.hpp"
 
-#ifdef MACOSX
-namespace supertux_apple {
-#  include <CoreFoundation/CoreFoundation.h>
-} // namespace supertux_apple
-#endif
-
 #include "addon/addon_manager.hpp"
 #include "audio/sound_manager.hpp"
 #include "control/joystickkeyboardcontroller.hpp"
@@ -147,7 +143,10 @@ Main::init_physfs(const char* argv0)
   PHYSFS_addToSearchPath(writedir.c_str(), 0);
 
   // when started from source dir...
-  std::string dir = PHYSFS_getBaseDir();
+  char* base_path = SDL_GetBasePath();
+  std::string dir = base_path;
+  SDL_free(base_path);
+
   if (dir[dir.length() - 1] != '/')
     dir += "/";
   dir += "data";
@@ -164,44 +163,6 @@ Main::init_physfs(const char* argv0)
     }
   }
 
-#ifdef MACOSX
-  {
-    using namespace supertux_apple;
-
-    // when started from Application file on Mac OS X...
-    char path[PATH_MAX];
-    CFBundleRef mainBundle = CFBundleGetMainBundle();
-    if(mainBundle == 0)
-      throw "Assertion failed: mainBundle != 0";
-    CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle);
-    if(mainBundleURL == 0)
-      throw "Assertion failed: mainBundleURL != 0";
-    CFStringRef pathStr = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);
-    if(pathStr == 0)
-      throw "Assertion failed: pathStr != 0";
-    CFStringGetCString(pathStr, path, PATH_MAX, kCFStringEncodingUTF8);
-    CFRelease(mainBundleURL);
-    CFRelease(pathStr);
-
-    dir = std::string(path) + "/Contents/Resources/data";
-    testfname = dir + "/credits.txt";
-    sourcedir = false;
-    f = fopen(testfname.c_str(), "r");
-    if(f) {
-      fclose(f);
-      if(!PHYSFS_addToSearchPath(dir.c_str(), 1)) {
-        log_warning << "Couldn't add '" << dir << "' to physfs searchpath: " << PHYSFS_getLastError() << std::endl;
-      } else {
-        sourcedir = true;
-      }
-    }
-  }
-#endif
-
-#ifdef _WIN32
-  PHYSFS_addToSearchPath(".\\data", 1);
-#endif
-
   if(!sourcedir) {
     std::string datadir = PHYSFS_getBaseDir();
     datadir = datadir.substr(0, datadir.rfind(INSTALL_SUBDIR_BIN));
@@ -317,6 +278,7 @@ Main::parse_commandline(int argc, char** argv)
       
       g_config->window_size     = Size(800, 600);
       g_config->fullscreen_size = Size(800, 600);
+      g_config->fullscreen_refresh_rate = 0;
       g_config->aspect_size     = Size(0, 0);  // auto detect
       
     } else if(arg == "--window" || arg == "-w") {
@@ -340,6 +302,7 @@ Main::parse_commandline(int argc, char** argv)
         {
           g_config->window_size     = Size(width, height);
           g_config->fullscreen_size = Size(width, height);
+          g_config->fullscreen_refresh_rate = 0;
         }
       }
     } else if(arg == "--aspect" || arg == "-a") {
@@ -435,7 +398,9 @@ Main::init_sdl()
   // just to be sure
   atexit(SDL_Quit);
 
-  SDL_EnableUNICODE(1);
+ // SDL_EnableUNICODE(1); //old code, mofif by giby 
+ //   SDL_JoystickID myID = SDL_JoystickInstanceID(myOpenedStick);
+  
 
   // wait 100ms and clear SDL event queue because sometimes we have random
   // joystick events in the queue on startup...
@@ -459,41 +424,24 @@ Main::init_rand()
 void
 Main::init_video()
 {
-  // FIXME: Add something here
-  SCREEN_WIDTH  = 800;
-  SCREEN_HEIGHT = 600;
-
-  context_pointer->init_renderer();
-  g_screen = SDL_GetVideoSurface();
+  SDL_SetWindowTitle(Renderer::instance()->get_window(), PACKAGE_NAME " " PACKAGE_VERSION);
 
-  SDL_WM_SetCaption(PACKAGE_NAME " " PACKAGE_VERSION, 0);
-
-  // set icon
-#ifdef MACOSX
   const char* icon_fname = "images/engine/icons/supertux-256x256.png";
-#else
-  const char* icon_fname = "images/engine/icons/supertux.xpm";
-#endif
-  SDL_Surface* icon;
-  try {
-    icon = IMG_Load_RW(get_physfs_SDLRWops(icon_fname), true);
-  } catch (const std::runtime_error& err) {
-    icon = 0;
-    log_warning << "Couldn't load icon '" << icon_fname << "': " << err.what() << std::endl;
+  SDL_Surface* icon = IMG_Load_RW(get_physfs_SDLRWops(icon_fname), true);
+  if (!icon)
+  {
+    log_warning << "Couldn't load icon '" << icon_fname << "': " << SDL_GetError() << std::endl;
   }
-  if(icon != 0) {
-    SDL_WM_SetIcon(icon, 0);
+  else
+  {
+    SDL_SetWindowIcon(Renderer::instance()->get_window(), icon);
     SDL_FreeSurface(icon);
   }
-  else {
-    log_warning << "Couldn't load icon '" << icon_fname << "'" << std::endl;
-  }
-
   SDL_ShowCursor(0);
 
   log_info << (g_config->use_fullscreen?"fullscreen ":"window ")
            << " Window: "     << g_config->window_size
-           << " Fullscreen: " << g_config->fullscreen_size
+           << " Fullscreen: " << g_config->fullscreen_size << "@" << g_config->fullscreen_refresh_rate
            << " Area: "       << g_config->aspect_size << std::endl;
 }
 
@@ -598,7 +546,9 @@ Main::run(int argc, char** argv)
       return 0;
 
     timelog("video");
-    DrawingContext context;
+    std::auto_ptr<Renderer> renderer(VideoSystem::new_renderer());
+    std::auto_ptr<Lightmap> lightmap(VideoSystem::new_lightmap());
+    DrawingContext context(*renderer, *lightmap);
     context_pointer = &context;
     init_video();
     
@@ -632,7 +582,7 @@ Main::run(int argc, char** argv)
       // So we simply mount that path here...
       std::string dir = FileSystem::dirname(g_config->start_level);
       std::string fileProtocol = "file://";
-      size_t position = dir.find(fileProtocol);
+      std::string::size_type position = dir.find(fileProtocol);
       if(position != std::string::npos) {
          dir = dir.replace(position, fileProtocol.length(), "");
       }
index c6bacb3..e4e1dcb 100644 (file)
@@ -59,12 +59,16 @@ JoystickMenu::recreateMenu()
   }
   add_inactive(-1,"");
   add_entry(SCAN_JOYSTICKS, _("Scan for Joysticks"));
+  //Show Joysticks currently activated: //edit by giby
+  SDL_Joystick *joy;
+  if (SDL_NumJoysticks() > 0) {
+    joy = SDL_JoystickOpen(0);
+  }
 
-  //Show Joysticks currently activated:
   for(std::vector<SDL_Joystick*>::iterator i = controller->joysticks.begin();
       i != controller->joysticks.end(); ++i) {
     if(*i != 0)
-      add_inactive(-1, SDL_JoystickName(SDL_JoystickIndex(*i)) );
+      add_inactive(-1, SDL_JoystickName(joy) );
   }
 
   add_hl();
index 883adef..bbdd1cf 100644 (file)
@@ -49,7 +49,7 @@ KeyboardMenu::~KeyboardMenu()
 {}
 
 std::string
-KeyboardMenu::get_key_name(SDLKey key)
+KeyboardMenu::get_key_name(SDL_Keycode key)
 {
   switch(key) {
     case SDLK_UNKNOWN:
@@ -79,7 +79,7 @@ KeyboardMenu::get_key_name(SDLKey key)
     case SDLK_LALT:
       return _("Left Alt");
     default:
-      return SDL_GetKeyName((SDLKey) key);
+      return SDL_GetKeyName((SDL_Keycode) key);
   }
 }
 
index f4435d1..b09c406 100644 (file)
@@ -28,7 +28,7 @@ public:
   ~KeyboardMenu();
 
   void update();
-  std::string get_key_name(SDLKey key);
+  std::string get_key_name(SDL_Keycode key);
   virtual void menu_action(MenuItem* item);
   JoystickKeyboardController* controller;
   void check_menu() {}
index 3948b0a..d65aa7d 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <algorithm>
 #include <sstream>
+#include <stdio.h>
 
 enum OptionsMenuIDs {
   MNID_FULLSCREEN,
@@ -105,43 +106,25 @@ OptionsMenu::OptionsMenu() :
     }
   }
   
-
-  SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_OPENGL);
-
-  if (modes == (SDL_Rect **)0) 
-  { // No resolutions at all available, bad
-
-  }
-  else if(modes == (SDL_Rect **)-1) 
-  { // All resolutions should work, so we fall back to hardcoded defaults
-    fullscreen_res->list.push_back("640x480");
-    fullscreen_res->list.push_back("800x600");
-    fullscreen_res->list.push_back("1024x768");
-    fullscreen_res->list.push_back("1152x864");
-    fullscreen_res->list.push_back("1280x960");
-    fullscreen_res->list.push_back("1280x1024");
-    fullscreen_res->list.push_back("1440x900");
-    fullscreen_res->list.push_back("1680x1050");
-    fullscreen_res->list.push_back("1600x1200");
-    fullscreen_res->list.push_back("1920x1080");
-    fullscreen_res->list.push_back("1920x1200");
-  }
-  else 
+  int display_mode_count = SDL_GetNumDisplayModes(0);
+  for(int i = 0; i < display_mode_count; ++i)
   {
-    for(int i = 0; modes[i]; ++i)
+    SDL_DisplayMode mode;
+    int ret = SDL_GetDisplayMode(0, i, &mode);
+    if (ret != 0)
     {
-      std::ostringstream out;          
-      out << modes[i]->w << "x" << modes[i]->h;
+      log_warning << "failed to get display mode: " << SDL_GetError() << std::endl;
+    }
+    else
+    {
+      std::ostringstream out;
+      out << mode.w << "x" << mode.h << "@" << mode.refresh_rate;
       fullscreen_res->list.push_back(out.str());
     }
-
-    // On Ubuntu/Linux resolutions are returned from highest to
-    // lowest, so reverse them
-    std::sort(fullscreen_res->list.begin(), fullscreen_res->list.end(), StringUtil::numeric_less);
   }
-  
+
   std::ostringstream out;
-  out << g_config->fullscreen_size.width << "x" << g_config->fullscreen_size.height;
+  out << g_config->fullscreen_size.width << "x" << g_config->fullscreen_size.height << "@" << g_config->fullscreen_refresh_rate;
   std::string fllscrn_sz = out.str();
   size_t cnt = 0;
   for (std::vector<std::string>::iterator i = fullscreen_res->list.begin(); i != fullscreen_res->list.end(); ++i) 
@@ -222,25 +205,25 @@ OptionsMenu::menu_action(MenuItem* item)
 {
   switch (item->id) {
     case MNID_ASPECTRATIO:
-    { 
-      if (item->list[item->selected] == _("auto"))
       {
-        g_config->aspect_size = Size(0, 0); // Magic values
-        Renderer::instance()->apply_config();
-        MenuManager::recalc_pos();
-      }
-      else if (sscanf(item->list[item->selected].c_str(), "%d:%d", 
-                      &g_config->aspect_size.width, &g_config->aspect_size.height) == 2)
-      {
-        Renderer::instance()->apply_config();
-        MenuManager::recalc_pos();
-      }
-      else
-      {
-        assert(!"This must not be reached");
+        if (item->list[item->selected] == _("auto"))
+        {
+          g_config->aspect_size = Size(0, 0); // Magic values
+          Renderer::instance()->apply_config();
+          MenuManager::recalc_pos();
+        }
+        else if (sscanf(item->list[item->selected].c_str(), "%d:%d",
+                        &g_config->aspect_size.width, &g_config->aspect_size.height) == 2)
+        {
+          Renderer::instance()->apply_config();
+          MenuManager::recalc_pos();
+        }
+        else
+        {
+          assert(!"This must not be reached");
+        }
       }
-    }
-    break;
+      break;
 
     case MNID_MAGNIFICATION:
       if (item->list[item->selected] == _("auto"))
@@ -256,10 +239,18 @@ OptionsMenu::menu_action(MenuItem* item)
       break;
 
     case MNID_FULLSCREEN_RESOLUTION:
-      if(sscanf(item->list[item->selected].c_str(), "%dx%d", 
-                &g_config->fullscreen_size.width, &g_config->fullscreen_size.height) == 2)
       {
-        // do nothing, changes are only applied when toggling fullscreen mode
+        int width;
+        int height;
+        int refresh_rate;
+        if(sscanf(item->list[item->selected].c_str(), "%dx%d@%d",
+                  &width, &height, &refresh_rate) == 3)
+        {
+          // do nothing, changes are only applied when toggling fullscreen mode
+          g_config->fullscreen_size.width = width;
+          g_config->fullscreen_size.height = height;
+          g_config->fullscreen_refresh_rate = refresh_rate;
+        }
       }      
       break;
 
index ffd9599..e1e7f12 100644 (file)
@@ -35,6 +35,7 @@
 #include "video/drawing_context.hpp"
 #include "video/renderer.hpp"
 
+#include <stdio.h>
 /** ticks (as returned from SDL_GetTicks) per frame */
 static const Uint32 TICKS_PER_FRAME = (Uint32) (1000.0 / LOGICAL_FPS);
 /** don't skip more than every 2nd frame */
@@ -190,7 +191,6 @@ void
 ScreenManager::process_events()
 {
   g_jk_controller->update();
-  Uint8* keystate = SDL_GetKeyState(NULL);
   SDL_Event event;
   while(SDL_PollEvent(&event)) 
   {
@@ -205,9 +205,15 @@ ScreenManager::process_events()
         quit();
         break;
               
-      case SDL_VIDEORESIZE:
-        Renderer::instance()->resize(event.resize.w, event.resize.h);
-        MenuManager::recalc_pos();
+      case SDL_WINDOWEVENT:
+        switch(event.window.event)
+        {
+          case SDL_WINDOWEVENT_RESIZED:
+            Renderer::instance()->resize(event.window.data1,
+                                         event.window.data2);
+            MenuManager::recalc_pos();
+            break;
+        }
         break;
             
       case SDL_KEYDOWN:
@@ -221,14 +227,13 @@ ScreenManager::process_events()
           Renderer::instance()->apply_config();
           MenuManager::recalc_pos();
         }
-        else if (event.key.keysym.sym == SDLK_PRINT ||
+        else if (event.key.keysym.sym == SDLK_PRINTSCREEN ||
                  event.key.keysym.sym == SDLK_F12)
         {
           take_screenshot();
         }
         else if (event.key.keysym.sym == SDLK_F1 &&
-                 (keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) &&
-                 keystate[SDLK_c])
+                 event.key.keysym.mod & KMOD_CTRL)
         {
           Console::instance->toggle();
           g_config->console_enabled = true;
index 0b56308..96d06ab 100644 (file)
@@ -31,9 +31,9 @@
 #include "video/texture_manager.hpp"
 #include "video/video_systems.hpp"
 
-DrawingContext::DrawingContext() :
-  renderer(0), 
-  lightmap(0),
+DrawingContext::DrawingContext(Renderer& renderer, Lightmap& lightmap) :
+  renderer(renderer),
+  lightmap(lightmap),
   transformstack(),
   transform(),
   blend_stack(),
@@ -53,23 +53,10 @@ DrawingContext::DrawingContext() :
 
 DrawingContext::~DrawingContext()
 {
-  delete renderer;
-  delete lightmap;
-
   obstack_free(&obst, NULL);
 }
 
 void
-DrawingContext::init_renderer()
-{
-  delete renderer;
-  delete lightmap;
-
-  renderer = VideoSystem::new_renderer();
-  lightmap = VideoSystem::new_lightmap();
-}
-
-void
 DrawingContext::draw_surface(SurfacePtr surface, const Vector& position,
                              float angle, const Color& color, const Blend& blend,
                              int layer)
@@ -325,9 +312,9 @@ DrawingContext::do_drawing()
 
   // PART1: create lightmap
   if(use_lightmap) {
-    lightmap->start_draw(ambient_color);
+    lightmap.start_draw(ambient_color);
     handle_drawing_requests(lightmap_requests);
-    lightmap->end_draw();
+    lightmap.end_draw();
 
     DrawingRequest* request = new(obst) DrawingRequest();
     request->target = NORMAL;
@@ -344,11 +331,11 @@ DrawingContext::do_drawing()
 
   // if a screenshot was requested, take one
   if (screenshot_requested) {
-    renderer->do_take_screenshot();
+    renderer.do_take_screenshot();
     screenshot_requested = false;
   }
 
-  renderer->flip();
+  renderer.flip();
 }
 
 class RequestPtrCompare
@@ -373,64 +360,64 @@ DrawingContext::handle_drawing_requests(DrawingRequests& requests)
       case NORMAL:
         switch(request.type) {
           case SURFACE:
-            renderer->draw_surface(request);
+            renderer.draw_surface(request);
             break;
           case SURFACE_PART:
-            renderer->draw_surface_part(request);
+            renderer.draw_surface_part(request);
             break;
           case GRADIENT:
-            renderer->draw_gradient(request);
+            renderer.draw_gradient(request);
             break;
           case TEXT:
           {
             const TextRequest* textrequest = (TextRequest*) request.request_data;
-            textrequest->font->draw(renderer, textrequest->text, request.pos,
+            textrequest->font->draw(&renderer, textrequest->text, request.pos,
                                     textrequest->alignment, request.drawing_effect, request.color, request.alpha);
           }
           break;
           case FILLRECT:
-            renderer->draw_filled_rect(request);
+            renderer.draw_filled_rect(request);
             break;
           case INVERSEELLIPSE:
-            renderer->draw_inverse_ellipse(request);
+            renderer.draw_inverse_ellipse(request);
             break;
           case DRAW_LIGHTMAP:
-            lightmap->do_draw();
+            lightmap.do_draw();
             break;
           case GETLIGHT:
-            lightmap->get_light(request);
+            lightmap.get_light(request);
             break;
         }
         break;
       case LIGHTMAP:
         switch(request.type) {
           case SURFACE:
-            lightmap->draw_surface(request);
+            lightmap.draw_surface(request);
             break;
           case SURFACE_PART:
-            lightmap->draw_surface_part(request);
+            lightmap.draw_surface_part(request);
             break;
           case GRADIENT:
-            lightmap->draw_gradient(request);
+            lightmap.draw_gradient(request);
             break;
           case TEXT:
           {
             const TextRequest* textrequest = (TextRequest*) request.request_data;
-            textrequest->font->draw(renderer, textrequest->text, request.pos,
+            textrequest->font->draw(&renderer, textrequest->text, request.pos,
                                     textrequest->alignment, request.drawing_effect, request.color, request.alpha);
           }
           break;
           case FILLRECT:
-            lightmap->draw_filled_rect(request);
+            lightmap.draw_filled_rect(request);
             break;
           case INVERSEELLIPSE:
             assert(!"InverseEllipse doesn't make sense on the lightmap");
             break;
           case DRAW_LIGHTMAP:
-            lightmap->do_draw();
+            lightmap.do_draw();
             break;
           case GETLIGHT:
-            lightmap->get_light(request);
+            lightmap.get_light(request);
             break;
         }
         break;
index 86c3c7a..13f28c9 100644 (file)
@@ -52,11 +52,9 @@ inline int next_po2(int val)
 class DrawingContext
 {
 public:
-  DrawingContext();
+  DrawingContext(Renderer& renderer, Lightmap& lightmap);
   ~DrawingContext();
 
-  void init_renderer();
-
   /// Adds a drawing request for a surface into the request list.
   void draw_surface(SurfacePtr surface, const Vector& position,
                     int layer);
@@ -154,8 +152,8 @@ private:
   };
 
 private:
-  Renderer *renderer;
-  Lightmap *lightmap;
+  Rendererrenderer;
+  Lightmaplightmap;
 
   /// the transform stack
   std::vector<Transform> transformstack;
index d9ccd08..00b7ec1 100644 (file)
@@ -206,6 +206,12 @@ Font::loadFontSurface(
       }
       else 
       {
+        if (y + char_height > surface->h)
+        {
+          log_warning << "error: font definition contains more letter then the images: " << glyphimage << std::endl;
+          goto abort;
+        }
+
         int left = x;
         while (left < x + char_width && vline_empty(surface, left, y, y + char_height, 64))
           left += 1;
@@ -234,7 +240,8 @@ Font::loadFontSurface(
       row++;
     }
   }
-  
+abort:
+
   if( surface != NULL ) {
     SDL_UnlockSurface(surface);
     SDL_FreeSurface(surface);
index f8a6735..8cf8494 100644 (file)
 #include "video/texture_manager.hpp"
 
 GLLightmap::GLLightmap() :
-  screen(),
   lightmap(),
   lightmap_width(),
   lightmap_height(),
   lightmap_uv_right(),
   lightmap_uv_bottom()
 {
-  screen = SDL_GetVideoSurface();
-
   lightmap_width = SCREEN_WIDTH / LIGHTMAP_DIV;
   lightmap_height = SCREEN_HEIGHT / LIGHTMAP_DIV;
   unsigned int width = next_po2(lightmap_width);
index af72e42..b440639 100644 (file)
@@ -34,7 +34,6 @@ public:
   void do_draw();
   void draw_surface(const DrawingRequest& request);
   void draw_surface_part(const DrawingRequest& request);
-  void draw_text(const DrawingRequest& request);
   void draw_gradient(const DrawingRequest& request);
   void draw_filled_rect(const DrawingRequest& request);
   void get_light(const DrawingRequest& request) const;
@@ -42,7 +41,6 @@ public:
 private:
   static const int LIGHTMAP_DIV = 5;
 
-  SDL_Surface* screen;
   boost::shared_ptr<GLTexture> lightmap;
   int lightmap_width;
   int lightmap_height;
index 6a2aa32..d24127c 100644 (file)
@@ -1,5 +1,6 @@
 //  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"
 #include "video/drawing_request.hpp"
 #include "video/gl/gl_surface_data.hpp"
 #include "video/gl/gl_texture.hpp"
+#include "video/util.hpp"
+
 #define LIGHTMAP_DIV 5
 
 #ifdef GL_VERSION_ES_CM_1_0
 #endif
 
 GLRenderer::GLRenderer() :
-  desktop_size(-1, -1),
-  screen_size(-1, -1),
+  window(),
+  desktop_size(0, 0),
+  screen_size(0, 0),
   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);
@@ -87,12 +89,12 @@ GLRenderer::GLRenderer() :
 
   // Init the projection matrix, viewport and stuff
   apply_config();
-  
+
   if(texture_manager == 0)
     texture_manager = new TextureManager();
   else
     texture_manager->reload_textures();
-  
+
 #ifndef GL_VERSION_ES_CM_1_0
   GLenum err = glewInit();
   if (GLEW_OK != err)
@@ -108,6 +110,8 @@ GLRenderer::GLRenderer() :
 
 GLRenderer::~GLRenderer()
 {
+  SDL_GL_DeleteContext(glcontext);
+  SDL_DestroyWindow(window);
 }
 
 void
@@ -187,7 +191,7 @@ GLRenderer::draw_surface_part(const DrawingRequest& request)
 void
 GLRenderer::draw_gradient(const DrawingRequest& request)
 {
-  const GradientRequest* gradientrequest 
+  const GradientRequest* gradientrequest
     = (GradientRequest*) request.request_data;
   const Color& top = gradientrequest->top;
   const Color& bottom = gradientrequest->bottom;
@@ -231,7 +235,7 @@ GLRenderer::draw_filled_rect(const DrawingRequest& request)
   glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
             fillrectrequest->color.blue, fillrectrequest->color.alpha);
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-  
+
   if (fillrectrequest->radius != 0.0f)
   {
     // draw round rect
@@ -309,7 +313,7 @@ GLRenderer::draw_inverse_ellipse(const DrawingRequest& request)
   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;
@@ -378,10 +382,10 @@ GLRenderer::draw_inverse_ellipse(const DrawingRequest& request)
   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
   glEnable(GL_TEXTURE_2D);
-  glColor4f(1, 1, 1, 1);    
+  glColor4f(1, 1, 1, 1);
 }
 
-void 
+void
 GLRenderer::do_take_screenshot()
 {
   // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
@@ -389,9 +393,9 @@ GLRenderer::do_take_screenshot()
   SDL_Surface *shot_surf;
   // create surface to hold screenshot
 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
-  shot_surf = SDL_CreateRGBSurface(SDL_HWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
+  shot_surf = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
 #else
-  shot_surf = SDL_CreateRGBSurface(SDL_HWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
+  shot_surf = SDL_CreateRGBSurface(0, 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;
@@ -454,16 +458,12 @@ void
 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);
 
   apply_config();
@@ -471,116 +471,51 @@ GLRenderer::resize(int w, int h)
 
 void
 GLRenderer::apply_config()
-{    
-  if (false)
-  {
-    log_info << "Applying Config:" 
-             << "\n  Desktop: " << desktop_size.width << "x" << desktop_size.height
-             << "\n  Window:  " << g_config->window_size
-             << "\n  FullRes: " << g_config->fullscreen_size
-             << "\n  Aspect:  " << g_config->aspect_size
-             << "\n  Magnif:  " << g_config->magnification
-             << std::endl;
-  }
-
-  float target_aspect = static_cast<float>(desktop_size.width) / static_cast<float>(desktop_size.height);
-  if (g_config->aspect_size != Size(0, 0))
-  {
-    target_aspect = float(g_config->aspect_size.width) / float(g_config->aspect_size.height);
-  }
-
-  float desktop_aspect = 4.0f / 3.0f; // random default fallback guess
-  if (desktop_size.width != -1 && desktop_size.height != -1)
-  {
-    desktop_aspect = float(desktop_size.width) / float(desktop_size.height);
-  }
-
-  Size screen_size;
-
-  // Get the screen width
-  if (g_config->use_fullscreen)
-  {
-    screen_size = g_config->fullscreen_size;
-    desktop_aspect = float(screen_size.width) / float(screen_size.height);
-  }
-  else
-  {
-    screen_size = g_config->window_size;
-  }
-
+{
   apply_video_mode(screen_size, g_config->use_fullscreen);
 
-  if (target_aspect > 1.0f)
+  Size target_size = g_config->use_fullscreen ?
+    g_config->fullscreen_size :
+    g_config->window_size;
+
+  float pixel_aspect_ratio = 1.0f;
+  if (g_config->aspect_size != Size(0, 0))
   {
-    SCREEN_WIDTH  = static_cast<int>(screen_size.width * (target_aspect / desktop_aspect));
-    SCREEN_HEIGHT = static_cast<int>(screen_size.height);
+    pixel_aspect_ratio = calculate_pixel_aspect_ratio(desktop_size,
+                                                      g_config->aspect_size);
   }
-  else
+  else if (g_config->use_fullscreen)
   {
-    SCREEN_WIDTH  = static_cast<int>(screen_size.width);
-    SCREEN_HEIGHT = static_cast<int>(screen_size.height  * (target_aspect / desktop_aspect));
+    pixel_aspect_ratio = calculate_pixel_aspect_ratio(desktop_size,
+                                                      target_size);
   }
 
   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 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 scale2  = float(max_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);
-    } 
-    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);
-  }
-  else
-  {
-    SCREEN_WIDTH  = static_cast<int>(SCREEN_WIDTH  / g_config->magnification);
-    SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT / g_config->magnification);
-
-    // This works by adding black borders around the screen to limit
-    // SCREEN_WIDTH/SCREEN_HEIGHT to max_size.width/max_size.height
-    Size new_size = screen_size;
-
-    if (SCREEN_WIDTH > max_size.width)
-    {
-      new_size.width = static_cast<int>((float) new_size.width * float(max_size.width)/SCREEN_WIDTH);
-      SCREEN_WIDTH = static_cast<int>(max_size.width);
-    }
+  Vector scale;
+  Size logical_size;
+  calculate_viewport(min_size, max_size, screen_size,
+                     pixel_aspect_ratio,
+                     g_config->magnification,
+                     scale,
+                     logical_size,
+                     viewport);
 
-    if (SCREEN_HEIGHT > max_size.height)
-    {
-      new_size.height = static_cast<int>((float) new_size.height * float(max_size.height)/SCREEN_HEIGHT);
-      SCREEN_HEIGHT = static_cast<int>(max_size.height);
-    }
+  SCREEN_WIDTH = logical_size.width;
+  SCREEN_HEIGHT = logical_size.height;
 
+  if (viewport.x != 0 || viewport.y != 0)
+  {
     // 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();
-
-    glViewport(std::max(0, (screen_size.width  - new_size.width)  / 2),
-               std::max(0, (screen_size.height - new_size.height) / 2),
-               std::min(new_size.width,  screen_size.width),
-               std::min(new_size.height, screen_size.height));
+    SDL_GL_SwapWindow(window);
   }
 
+  glViewport(viewport.x, viewport.y, viewport.w, viewport.h);
+
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
 
@@ -595,32 +530,84 @@ GLRenderer::apply_config()
 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;
+      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, SDL_WINDOW_FULLSCREEN);
+      }
     }
     else
     {
-      flags |= SDL_RESIZABLE;
+      SDL_SetWindowFullscreen(window, 0);
     }
+  }
+  else
+  {
+    int flags = SDL_WINDOW_OPENGL;
 
-    if (SDL_Surface *screen = SDL_SetVideoMode(size.width, size.height, 0, flags))
+    if (fullscreen)
     {
-      screen_size = Size(screen->w, screen->h);
-      fullscreen_active = 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;
+
+      SCREEN_WIDTH = size.width;
+      SCREEN_HEIGHT = size.height;
+
+      fullscreen_active = fullscreen;
+    }
   }
 }
 
+Vector
+GLRenderer::to_logical(int physical_x, int physical_y)
+{
+  return Vector(static_cast<float>(physical_x - viewport.x) * SCREEN_WIDTH / viewport.w,
+                static_cast<float>(physical_y - viewport.y) * SCREEN_HEIGHT / viewport.h);
+}
+
+void
+GLRenderer::set_gamma(float gamma)
+{
+  Uint16 ramp[256];
+  SDL_CalculateGammaRamp(gamma, ramp);
+  SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
+}
+
 /* EOF */
index d5d9995..d1b7026 100644 (file)
@@ -21,6 +21,7 @@
 #include "video/drawing_request.hpp"
 #include "video/renderer.hpp"
 
+#include "SDL.h"
 #include <math.h>
 
 namespace {
@@ -35,13 +36,13 @@ inline void intern_draw(float left, float top, float right, float bottom,
 {
   if(effect & HORIZONTAL_FLIP)
     std::swap(uv_left, uv_right);
-  if(effect & VERTICAL_FLIP) 
+
+  if(effect & VERTICAL_FLIP)
     std::swap(uv_top, uv_bottom);
 
   glBlendFunc(blend.sfactor, blend.dfactor);
   glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
+
   // unrotated blit
   if (angle == 0.0f) {
     float vertices[] = {
@@ -106,10 +107,13 @@ inline void intern_draw(float left, float top, float right, float bottom,
 class GLRenderer : public Renderer
 {
 private:
+  SDL_Window* window;
+  SDL_GLContext glcontext;
+  SDL_Rect viewport;
   Size desktop_size;
   Size screen_size;
   bool fullscreen_active;
-       
+
   GLuint last_texture;
 
 public:
@@ -118,7 +122,6 @@ public:
 
   void draw_surface(const DrawingRequest& request);
   void draw_surface_part(const DrawingRequest& request);
-  void draw_text(const DrawingRequest& request);
   void draw_gradient(const DrawingRequest& request);
   void draw_filled_rect(const DrawingRequest& request);
   void draw_inverse_ellipse(const DrawingRequest& request);
@@ -127,6 +130,9 @@ public:
   void resize(int w, int h);
   void apply_config();
   void apply_video_mode(const Size& size, bool fullscreen);
+  Vector to_logical(int physical_x, int physical_y);
+  void set_gamma(float gamma);
+  SDL_Window* get_window() const { return window; }
 };
 
 #endif
index 952e424..298e0f7 100644 (file)
@@ -93,11 +93,11 @@ GLTexture::GLTexture(SDL_Surface* image) :
   image_height = image->h;
 
 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
-  SDL_Surface* convert = SDL_CreateRGBSurface(SDL_HWSURFACE,
+  SDL_Surface* convert = SDL_CreateRGBSurface(0,
                                               texture_width, texture_height, 32,
                                               0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
 #else
-  SDL_Surface* convert = SDL_CreateRGBSurface(SDL_HWSURFACE,
+  SDL_Surface* convert = SDL_CreateRGBSurface(0,
                                               texture_width, texture_height, 32,
                                               0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
 #endif
@@ -106,7 +106,7 @@ GLTexture::GLTexture(SDL_Surface* image) :
     throw std::runtime_error("Couldn't create texture: out of memory");
   }
 
-  SDL_SetAlpha(image, 0, 0);
+  SDL_SetSurfaceBlendMode(image, SDL_BLENDMODE_NONE);
   SDL_BlitSurface(image, 0, convert, 0);
 
   assert_gl("before creating texture");
index 8bb39c7..a2a2a50 100644 (file)
@@ -52,6 +52,9 @@ public:
   virtual void flip() = 0;
   virtual void resize(int w, int h) = 0;
   virtual void apply_config() = 0;
+  virtual Vector to_logical(int physical_x, int physical_y) = 0;
+  virtual void set_gamma(float gamma) = 0;
+  virtual SDL_Window* get_window() const = 0;
 
   static Renderer* instance() { assert(instance_); return instance_; }
   
index b523fbc..d714960 100644 (file)
 #include "video/sdl/sdl_lightmap.hpp"
 #include "video/sdl/sdl_surface_data.hpp"
 #include "video/sdl/sdl_texture.hpp"
+#include "video/sdl/sdl_renderer.hpp"
+#include "video/sdl/sdl_painter.hpp"
 
 SDLLightmap::SDLLightmap() :
-  screen(),
-  red_channel(),
-  blue_channel(),
-  green_channel(),
+  renderer(static_cast<SDLRenderer*>(Renderer::instance())->get_sdl_renderer()),
   width(),
   height(),
-  numerator(),
-  denominator(),
   LIGHTMAP_DIV()
 {
-  screen = SDL_GetVideoSurface();
+  LIGHTMAP_DIV = 8;
 
-  //float xfactor = 1.0f; // FIXME: (float) config->screenwidth / SCREEN_WIDTH;
-  //float yfactor = 1.0f; // FIXME: (float) config->screenheight / SCREEN_HEIGHT;
+  width = 800; //screen->w / LIGHTMAP_DIV;
+  height = 600; //screen->h / LIGHTMAP_DIV;
 
-  numerator = 1;
-  denominator = 1;
-
-  /* FIXME:
-     if(xfactor < yfactor)
-     {
-     numerator = config->screenwidth;
-     denominator = SCREEN_WIDTH;
-     }
-     else
-     {
-     numerator = config->screenheight;
-     denominator = SCREEN_HEIGHT;
-     }
-  */
-
-  LIGHTMAP_DIV = 8 * numerator / denominator;
-
-  width = screen->w / LIGHTMAP_DIV;
-  height = screen->h / LIGHTMAP_DIV;
-
-  red_channel = (Uint8 *)malloc(width * height * sizeof(Uint8));
-  green_channel = (Uint8 *)malloc(width * height * sizeof(Uint8));
-  blue_channel = (Uint8 *)malloc(width * height * sizeof(Uint8));
+  SDL_Renderer* renderer = static_cast<SDLRenderer*>(Renderer::instance())->get_sdl_renderer();
+  texture = SDL_CreateTexture(renderer,
+                              SDL_PIXELFORMAT_RGB888,
+                              SDL_TEXTUREACCESS_TARGET,
+                              width, height);
+  if (!texture)
+  {
+    std::stringstream msg;
+    msg << "Couldn't create lightmap texture: " << SDL_GetError();
+    throw std::runtime_error(msg.str());
+  }
 }
 
 SDLLightmap::~SDLLightmap()
 {
-  free(red_channel);
-  free(green_channel);
-  free(blue_channel);
+  SDL_DestroyTexture(texture);
 }
 
 void
 SDLLightmap::start_draw(const Color &ambient_color)
 {
-  memset(red_channel, (Uint8) (ambient_color.red * 255), width * height * sizeof(Uint8));
-  memset(green_channel, (Uint8) (ambient_color.green * 255), width * height * sizeof(Uint8));
-  memset(blue_channel, (Uint8) (ambient_color.blue * 255), width * height * sizeof(Uint8));
+  SDL_SetRenderTarget(renderer, texture);
+  Uint8 r = static_cast<Uint8>(ambient_color.red * 255);
+  Uint8 g = static_cast<Uint8>(ambient_color.green * 255);
+  Uint8 b = static_cast<Uint8>(ambient_color.blue * 255);
+
+  SDL_SetRenderDrawColor(renderer, r, g, b, 255);
+  SDL_RenderClear(renderer);
 }
 
 void
 SDLLightmap::end_draw()
 {
+  SDL_SetRenderTarget(renderer, NULL);
 }
 
-//#define BILINEAR
-
-#ifdef BILINEAR
-namespace {
-
-void merge(Uint8 color[3], Uint8 color0[3], Uint8 color1[3], int rem, int total)
-{
-  color[0] = (color0[0] * (total - rem) + color1[0] * rem) / total;
-  color[1] = (color0[1] * (total - rem) + color1[1] * rem) / total;
-  color[2] = (color0[2] * (total - rem) + color1[2] * rem) / total;
-}
-
-} // namespace
-#endif
-
 void
 SDLLightmap::do_draw()
 {
-  // FIXME: This is really slow
-  if(LIGHTMAP_DIV == 1)
-  {
-    int bpp = screen->format->BytesPerPixel;
-    if(SDL_MUSTLOCK(screen))
-    {
-      SDL_LockSurface(screen);
-    }
-    Uint8 *pixel = (Uint8 *) screen->pixels;
-    int loc = 0;
-    for(int y = 0;y < height;y++) {
-      for(int x = 0;x < width;x++, pixel += bpp, loc++) {
-        if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff)
-        {
-          continue;
-        }
-        Uint32 mapped = 0;
-        switch(bpp) {
-          case 1:
-            mapped = *pixel;
-            break;
-          case 2:
-            mapped = *(Uint16 *)pixel;
-            break;
-          case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-            mapped |= pixel[0] << 16;
-            mapped |= pixel[1] << 8;
-            mapped |= pixel[2] << 0;
-#else
-            mapped |= pixel[0] << 0;
-            mapped |= pixel[1] << 8;
-            mapped |= pixel[2] << 16;
-#endif
-            break;
-          case 4:
-            mapped = *(Uint32 *)pixel;
-            break;
-        }
-        Uint8 red, green, blue, alpha;
-        SDL_GetRGBA(mapped, screen->format, &red, &green, &blue, &alpha);
-        red = (red * red_channel[loc]) >> 8;
-        green = (green * green_channel[loc]) >> 8;
-        blue = (blue * blue_channel[loc]) >> 8;
-        mapped = SDL_MapRGBA(screen->format, red, green, blue, alpha);
-        switch(bpp) {
-          case 1:
-            *pixel = mapped;
-            break;
-          case 2:
-            *(Uint16 *)pixel = mapped;
-            break;
-          case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-            pixel[0] = (mapped >> 16) & 0xff;
-            pixel[1] = (mapped >> 8) & 0xff;
-            pixel[2] = (mapped >> 0) & 0xff;
-#else
-            pixel[0] = (mapped >> 0) & 0xff;
-            pixel[1] = (mapped >> 8) & 0xff;
-            pixel[2] = (mapped >> 16) & 0xff;
-#endif
-            break;
-          case 4:
-            *(Uint32 *)pixel = mapped;
-            break;
-        }
-      }
-      pixel += screen->pitch - width * bpp;
-    }
-    if(SDL_MUSTLOCK(screen))
-    {
-      SDL_UnlockSurface(screen);
-    }
-  }
-  else
-  {
-    int bpp = screen->format->BytesPerPixel;
-    if(SDL_MUSTLOCK(screen))
-    {
-      SDL_LockSurface(screen);
-    }
-    Uint8 *div_pixel = (Uint8 *) screen->pixels;
-    int loc = 0;
-    for(int y = 0;y < height;y++) {
-      for(int x = 0;x < width;x++, div_pixel += bpp * LIGHTMAP_DIV, loc++) {
-        if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff)
-        {
-          continue;
-        }
-        Uint8 *pixel = div_pixel;
-        for(int div_y = 0;div_y < LIGHTMAP_DIV;div_y++) {
-          for(int div_x = 0;div_x < LIGHTMAP_DIV;pixel += bpp, div_x++) {
-            Uint32 mapped = 0;
-            switch(bpp) {
-              case 1:
-                mapped = *pixel;
-                break;
-              case 2:
-                mapped = *(Uint16 *)pixel;
-                break;
-              case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-                mapped |= pixel[0] << 16;
-                mapped |= pixel[1] << 8;
-                mapped |= pixel[2] << 0;
-#else
-                mapped |= pixel[0] << 0;
-                mapped |= pixel[1] << 8;
-                mapped |= pixel[2] << 16;
-#endif
-                break;
-              case 4:
-                mapped = *(Uint32 *)pixel;
-                break;
-            }
-            Uint8 red, green, blue, alpha;
-            SDL_GetRGBA(mapped, screen->format, &red, &green, &blue, &alpha);
-
-#ifdef BILINEAR
-            int xinc = (x + 1 != width ? 1 : 0);
-            int yinc = (y + 1 != height ? width : 0);
-            Uint8 color00[3], color01[3], color10[3], color11[3];
-            {
-              color00[0] = red_channel[loc];
-              color00[1] = green_channel[loc];
-              color00[2] = blue_channel[loc];
-            }
-            {
-              color01[0] = red_channel[loc + xinc];
-              color01[1] = green_channel[loc + xinc];
-              color01[2] = blue_channel[loc + xinc];
-            }
-            {
-              color10[0] = red_channel[loc + yinc];
-              color10[1] = green_channel[loc + yinc];
-              color10[2] = blue_channel[loc + yinc];
-            }
-            {
-              color11[0] = red_channel[loc + yinc + xinc];
-              color11[1] = green_channel[loc + yinc + xinc];
-              color11[2] = blue_channel[loc + yinc + xinc];
-            }
-            Uint8 color0[3], color1[3], color[3];
-            merge(color0, color00, color01, div_x, LIGHTMAP_DIV);
-            merge(color1, color10, color11, div_x, LIGHTMAP_DIV);
-            merge(color, color0, color1, div_y, LIGHTMAP_DIV);
-            red = (red * color[0]) >> 8;
-            green = (green * color[1]) >> 8;
-            blue = (blue * color[2]) >> 8;
-#else
-            red = (red * red_channel[loc]) >> 8;
-            green = (green * green_channel[loc]) >> 8;
-            blue = (blue * blue_channel[loc]) >> 8;
-#endif
-
-            mapped = SDL_MapRGBA(screen->format, red, green, blue, alpha);
-            switch(bpp) {
-              case 1:
-                *pixel = mapped;
-                break;
-              case 2:
-                *(Uint16 *)pixel = mapped;
-                break;
-              case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-                pixel[0] = (mapped >> 16) & 0xff;
-                pixel[1] = (mapped >> 8) & 0xff;
-                pixel[2] = (mapped >> 0) & 0xff;
-#else
-                pixel[0] = (mapped >> 0) & 0xff;
-                pixel[1] = (mapped >> 8) & 0xff;
-                pixel[2] = (mapped >> 16) & 0xff;
-#endif
-                break;
-              case 4:
-                *(Uint32 *)pixel = mapped;
-                break;
-            }
-          }
-          pixel += screen->pitch - LIGHTMAP_DIV * bpp;
-        }
-      }
-      div_pixel += (screen->pitch - width * bpp) * LIGHTMAP_DIV;
-    }
-    if(SDL_MUSTLOCK(screen))
-    {
-      SDL_UnlockSurface(screen);
-    }
-  }
-}
-
-void
-SDLLightmap::light_blit(SDL_Surface *src, SDL_Rect *src_rect, int dstx, int dsty)
-{
-  dstx /= LIGHTMAP_DIV;
-  dsty /= LIGHTMAP_DIV;
-  int srcx = src_rect->x / LIGHTMAP_DIV;
-  int srcy = src_rect->y / LIGHTMAP_DIV;
-  int blit_width = src_rect->w / LIGHTMAP_DIV;
-  int blit_height = src_rect->h / LIGHTMAP_DIV;
-  int bpp = src->format->BytesPerPixel;
-  if(SDL_MUSTLOCK(src))
-  {
-    SDL_LockSurface(src);
-  }
-  Uint8 *pixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
-  int loc = dsty * width + dstx;
-  for(int y = 0;y < blit_height;y++) {
-    for(int x = 0;x < blit_width;x++, pixel += bpp * LIGHTMAP_DIV, loc++) {
-      if(x + dstx < 0 || y + dsty < 0 || x + dstx >= width || y + dsty >= height)
-      {
-        continue;
-      }
-      if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff)
-      {
-        continue;
-      }
+  SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_MOD);
 
-      Uint32 mapped = 0;
-      switch(bpp) {
-        case 1:
-          mapped = *pixel;
-          break;
-        case 2:
-          mapped = *(Uint16 *)pixel;
-          break;
-        case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-          mapped |= pixel[0] << 16;
-          mapped |= pixel[1] << 8;
-          mapped |= pixel[2] << 0;
-#else
-          mapped |= pixel[0] << 0;
-          mapped |= pixel[1] << 8;
-          mapped |= pixel[2] << 16;
-#endif
-          break;
-        case 4:
-          mapped = *(Uint32 *)pixel;
-          break;
-      }
-      Uint8 red, green, blue, alpha;
-      SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
+  SDL_Rect dst_rect;
+  dst_rect.x = 0;
+  dst_rect.y = 0;
+  dst_rect.w = width;
+  dst_rect.h = height;
 
-      if(red != 0)
-      {
-        int redsum = red_channel[loc] + (red * alpha >> 8);
-        red_channel[loc] = redsum & ~0xff ? 0xff : redsum;
-      }
-      if(green != 0)
-      {
-        int greensum = green_channel[loc] + (green * alpha >> 8);
-        green_channel[loc] = greensum & ~0xff ? 0xff : greensum;
-      }
-      if(blue != 0)
-      {
-        int bluesum = blue_channel[loc] + (blue * alpha >> 8);
-        blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum;
-      }
-    }
-    pixel += (src->pitch - blit_width * bpp) * LIGHTMAP_DIV;
-    loc += width - blit_width;
-  }
-  if(SDL_MUSTLOCK(src))
-  {
-    SDL_UnlockSurface(src);
-  }
+  SDL_RenderCopy(renderer, texture, NULL, &dst_rect);
 }
 
-/*void Lightmap::light_blit(SDL_Surface *src, SDL_Rect *src_rect, int dstx, int dsty)
-  {
-  int bpp = src->format->BytesPerPixel;
-  if(SDL_MUSTLOCK(src))
-  {
-  SDL_LockSurface(src);
-  }
-  Uint8 *pixel = (Uint8 *) src->pixels + src_rect->y * src->pitch + src_rect->x * bpp;
-  int loc = dsty * width + dstx;
-  for(int y = 0;y < src_rect->h;y++) {
-  for(int x = 0;x < src_rect->w;x++, pixel += bpp, loc++) {
-  if(x + dstx < 0 || y + dsty < 0 || x + dstx >= width || y + dsty >= height)
-  {
-  continue;
-  }
-  if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff)
-  {
-  continue;
-  }
-
-  Uint32 mapped = 0;
-  switch(bpp) {
-  case 1:
-  mapped = *pixel;
-  break;
-  case 2:
-  mapped = *(Uint16 *)pixel;
-  break;
-  case 3:
-  #if SDL_BYTEORDER == SDL_BIG_ENDIAN
-  mapped |= pixel[0] << 16;
-  mapped |= pixel[1] << 8;
-  mapped |= pixel[2] << 0;
-  #else
-  mapped |= pixel[0] << 0;
-  mapped |= pixel[1] << 8;
-  mapped |= pixel[2] << 16;
-  #endif
-  break;
-  case 4:
-  mapped = *(Uint32 *)pixel;
-  break;
-  }
-  Uint8 red, green, blue, alpha;
-  SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
-
-  if(red != 0)
-  {
-  int redsum = red_channel[loc] + (red * alpha >> 8);
-  red_channel[loc] = redsum & ~0xff ? 0xff : redsum;
-  }
-  if(green != 0)
-  {
-  int greensum = green_channel[loc] + (green * alpha >> 8);
-  green_channel[loc] = greensum & ~0xff ? 0xff : greensum;
-  }
-  if(blue != 0)
-  {
-  int bluesum = blue_channel[loc] + (blue * alpha >> 8);
-  blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum;
-  }
-  }
-  pixel += src->pitch - src_rect->w * bpp;
-  loc += width - src_rect->w;
-  }
-  if(SDL_MUSTLOCK(src))
-  {
-  SDL_UnlockSurface(src);
-  }
-  }*/
-
 void
 SDLLightmap::draw_surface(const DrawingRequest& request)
 {
-  if((request.color.red == 0.0 && request.color.green == 0.0 && request.color.blue == 0.0) || request.color.alpha == 0.0 || request.alpha == 0.0)
-  {
-    return;
-  }
-  //FIXME: support parameters request.alpha, request.angle, request.blend
-  const Surface* surface = (const Surface*) request.request_data;
-  boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->get_texture());
-  SDLSurfaceData *surface_data = reinterpret_cast<SDLSurfaceData *>(surface->get_surface_data());
-
-  DrawingEffect effect = request.drawing_effect;
-  if (surface->get_flipx()) effect = HORIZONTAL_FLIP;
-
-  SDL_Surface *transform = sdltexture->get_transform(request.color, effect);
-
-  // get and check SDL_Surface
-  if (transform == 0) {
-    std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
-    return;
-  }
-
-  SDL_Rect *src_rect = surface_data->get_src_rect(effect);
-  int dstx = (int) request.pos.x * numerator / denominator;
-  int dsty = (int) request.pos.y * numerator / denominator;
-  light_blit(transform, src_rect, dstx, dsty);
+  SDLPainter::draw_surface(renderer, request);
 }
 
 void
 SDLLightmap::draw_surface_part(const DrawingRequest& request)
 {
-  const SurfacePartRequest* surfacepartrequest
-    = (SurfacePartRequest*) request.request_data;
-
-  const Surface* surface = surfacepartrequest->surface;
-  boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->get_texture());
-
-  DrawingEffect effect = request.drawing_effect;
-  if (surface->get_flipx()) effect = HORIZONTAL_FLIP;
-
-  SDL_Surface *transform = sdltexture->get_transform(Color(1.0, 1.0, 1.0), effect);
-
-  // get and check SDL_Surface
-  if (transform == 0) {
-    std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
-    return;
-  }
-
-  int ox, oy;
-  if (effect == HORIZONTAL_FLIP)
-  {
-    ox = sdltexture->get_texture_width() - surface->get_x() - (int) surfacepartrequest->size.x;
-  }
-  else
-  {
-    ox = surface->get_x();
-  }
-  if (effect == VERTICAL_FLIP)
-  {
-    oy = sdltexture->get_texture_height() - surface->get_y() - (int) surfacepartrequest->size.y;
-  }
-  else
-  {
-    oy = surface->get_y();
-  }
-
-  SDL_Rect src_rect;
-  src_rect.x = (ox + (int) surfacepartrequest->source.x) * numerator / denominator;
-  src_rect.y = (oy + (int) surfacepartrequest->source.y) * numerator / denominator;
-  src_rect.w = (int) surfacepartrequest->size.x * numerator / denominator;
-  src_rect.h = (int) surfacepartrequest->size.y * numerator / denominator;
-  int dstx = (int) request.pos.x * numerator / denominator;
-  int dsty = (int) request.pos.y * numerator / denominator;
-  light_blit(transform, &src_rect, dstx, dsty);
+  SDLPainter::draw_surface_part(renderer, request);
 }
 
 void
 SDLLightmap::draw_gradient(const DrawingRequest& request)
 {
-  const GradientRequest* gradientrequest 
-    = (GradientRequest*) request.request_data;
-  const Color& top = gradientrequest->top;
-  const Color& bottom = gradientrequest->bottom;
-
-  int loc = 0;
-  for(int y = 0;y < height;++y)
-  {
-    Uint8 red = (Uint8)((((float)(top.red-bottom.red)/(0-height)) * y + top.red) * 255);
-    Uint8 green = (Uint8)((((float)(top.green-bottom.green)/(0-height)) * y + top.green) * 255);
-    Uint8 blue = (Uint8)((((float)(top.blue-bottom.blue)/(0-height)) * y + top.blue) * 255);
-    Uint8 alpha = (Uint8)((((float)(top.alpha-bottom.alpha)/(0-height)) * y + top.alpha) * 255);
-    for(int x = 0;x < width;x++, loc++) {
-      if(red != 0)
-      {
-        int redsum = red_channel[loc] + (red * alpha >> 8);
-        red_channel[loc] = redsum & ~0xff ? 0xff : redsum;
-      }
-      if(green != 0)
-      {
-        int greensum = green_channel[loc] + (green * alpha >> 8);
-        green_channel[loc] = greensum & ~0xff ? 0xff : greensum;
-      }
-      if(blue != 0)
-      {
-        int bluesum = blue_channel[loc] + (blue * alpha >> 8);
-        blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum;
-      }
-    }
-  }
+  SDLPainter::draw_gradient(renderer, request);
 }
 
 void
 SDLLightmap::draw_filled_rect(const DrawingRequest& request)
 {
-  const FillRectRequest* fillrectrequest
-    = (FillRectRequest*) request.request_data;
-
-  int rect_x = (int) (request.pos.x * width / SCREEN_WIDTH);
-  int rect_y = (int) (request.pos.y * height / SCREEN_HEIGHT);
-  int rect_w = (int) (fillrectrequest->size.x * width / SCREEN_WIDTH);
-  int rect_h = (int) (fillrectrequest->size.y * height / SCREEN_HEIGHT);
-  Uint8 red = (Uint8) (fillrectrequest->color.red * fillrectrequest->color.alpha * 255);
-  Uint8 green = (Uint8) (fillrectrequest->color.green * fillrectrequest->color.alpha * 255);
-  Uint8 blue = (Uint8) (fillrectrequest->color.blue * fillrectrequest->color.alpha * 255);
-  if(red == 0 && green == 0 && blue == 0)
-  {
-    return;
-  }
-  for(int y = rect_y;y < rect_y + rect_h;y++) {
-    for(int x = rect_x;x < rect_x + rect_w;x++) {
-      int loc = y * width + x;
-      if(red != 0)
-      {
-        int redsum = red_channel[loc] + red;
-        red_channel[loc] = redsum & ~0xff ? 0xff : redsum;
-      }
-      if(green != 0)
-      {
-        int greensum = green_channel[loc] + green;
-        green_channel[loc] = greensum & ~0xff ? 0xff : greensum;
-      }
-      if(blue != 0)
-      {
-        int bluesum = blue_channel[loc] + blue;
-        blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum;
-      }
-    }
-  }
+  SDLPainter::draw_filled_rect(renderer, request);
 }
 
 void
@@ -599,10 +114,27 @@ SDLLightmap::get_light(const DrawingRequest& request) const
   const GetLightRequest* getlightrequest 
     = (GetLightRequest*) request.request_data;
 
-  int x = (int) (request.pos.x * width / SCREEN_WIDTH);
-  int y = (int) (request.pos.y * height / SCREEN_HEIGHT);
-  int loc = y * width + x;
-  *(getlightrequest->color_ptr) = Color(((float)red_channel[loc])/255, ((float)green_channel[loc])/255, ((float)blue_channel[loc])/255);
+  SDL_Rect rect;
+  rect.x = static_cast<int>(request.pos.x * width / SCREEN_WIDTH);
+  rect.y = static_cast<int>(request.pos.y * height / SCREEN_HEIGHT);
+  rect.w = 1;
+  rect.h = 1;
+
+  SDL_SetRenderTarget(renderer, texture);
+  Uint8 pixel[4];
+  int ret = SDL_RenderReadPixels(renderer, &rect,
+                                 SDL_PIXELFORMAT_RGB888,
+                                 pixel,
+                                 1);
+  if (ret != 0)
+  {
+    log_warning << "failed to read pixels: " << SDL_GetError() << std::endl;
+  }
+  SDL_SetRenderTarget(renderer, 0);
+
+  *(getlightrequest->color_ptr) = Color(pixel[2] / 255.0f,
+                                        pixel[1] / 255.0f,
+                                        pixel[0] / 255.0f);
 }
 
 /* EOF */
index 4719c38..df451be 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "video/lightmap.hpp"
 
+#include "SDL.h"
+
 class Color;
 struct DrawingRequest;
 
@@ -31,26 +33,21 @@ public:
   void start_draw(const Color &ambient_color);
   void end_draw();
   void do_draw();
+
   void draw_surface(const DrawingRequest& request);
   void draw_surface_part(const DrawingRequest& request);
-  void draw_text(const DrawingRequest& request);
   void draw_gradient(const DrawingRequest& request);
   void draw_filled_rect(const DrawingRequest& request);
+
   void get_light(const DrawingRequest& request) const;
 
 private:
-  SDL_Surface* screen;
-  Uint8 *red_channel;
-  Uint8 *blue_channel;
-  Uint8 *green_channel;
+  SDL_Renderer* renderer;
+  SDL_Texture* texture;
   int width;
   int height;
-  int numerator;
-  int denominator;
   int LIGHTMAP_DIV;
 
-  void light_blit(SDL_Surface *src, SDL_Rect *src_rect, int dstx, int dsty);
-
 private:
   SDLLightmap(const SDLLightmap&);
   SDLLightmap& operator=(const SDLLightmap&);
diff --git a/src/video/sdl/sdl_painter.cpp b/src/video/sdl/sdl_painter.cpp
new file mode 100644 (file)
index 0000000..b6dbbe0
--- /dev/null
@@ -0,0 +1,299 @@
+//  SuperTux
+//  Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
+//
+//  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
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "video/sdl/sdl_painter.hpp"
+
+#include "SDL.h"
+
+#include "util/log.hpp"
+#include "video/drawing_request.hpp"
+#include "video/sdl/sdl_texture.hpp"
+
+namespace {
+
+SDL_BlendMode blend2sdl(const Blend& blend)
+{
+  if (blend.sfactor == GL_ONE &&
+      blend.dfactor == GL_ZERO)
+  {
+    return SDL_BLENDMODE_NONE;
+  }
+  else if (blend.sfactor == GL_SRC_ALPHA &&
+           blend.dfactor == GL_ONE_MINUS_SRC_ALPHA)
+  {
+    return SDL_BLENDMODE_BLEND;
+  }
+  else if (blend.sfactor == GL_SRC_ALPHA &&
+           blend.dfactor == GL_ONE)
+  {
+    return SDL_BLENDMODE_ADD;
+  }
+  else if (blend.sfactor == GL_DST_COLOR &&
+           blend.dfactor == GL_ZERO)
+  {
+    return SDL_BLENDMODE_MOD;
+  }
+  else
+  {
+    log_warning << "unknown blend mode combinations: sfactor=" << blend.sfactor << " dfactor=" << blend.dfactor << std::endl;
+    return SDL_BLENDMODE_BLEND;
+  }
+}
+
+} // namespace
+
+void
+SDLPainter::draw_surface(SDL_Renderer* renderer, const DrawingRequest& request)
+{
+  const Surface* surface = (const Surface*) request.request_data;
+  boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->get_texture());
+
+  SDL_Rect dst_rect;
+  dst_rect.x = request.pos.x;
+  dst_rect.y = request.pos.y;
+  dst_rect.w = sdltexture->get_image_width();
+  dst_rect.h = sdltexture->get_image_height();
+
+  Uint8 r = static_cast<Uint8>(request.color.red * 255);
+  Uint8 g = static_cast<Uint8>(request.color.green * 255);
+  Uint8 b = static_cast<Uint8>(request.color.blue * 255);
+  Uint8 a = static_cast<Uint8>(request.color.alpha * request.alpha * 255);
+  SDL_SetTextureColorMod(sdltexture->get_texture(), r, g, b);
+  SDL_SetTextureAlphaMod(sdltexture->get_texture(), a);
+  SDL_SetTextureBlendMode(sdltexture->get_texture(), blend2sdl(request.blend));
+
+  SDL_RendererFlip flip = SDL_FLIP_NONE;
+  if (surface->get_flipx() || request.drawing_effect == HORIZONTAL_FLIP)
+  {
+    flip = SDL_FLIP_HORIZONTAL;
+  }
+  else if (request.drawing_effect == VERTICAL_FLIP)
+  {
+    flip = SDL_FLIP_VERTICAL;
+  }
+
+  SDL_RenderCopyEx(renderer, sdltexture->get_texture(), NULL, &dst_rect, request.angle, NULL, flip);
+}
+
+void
+SDLPainter::draw_surface_part(SDL_Renderer* renderer, const DrawingRequest& request)
+{
+  //FIXME: support parameters request.blend
+  const SurfacePartRequest* surface = (const SurfacePartRequest*) request.request_data;
+  const SurfacePartRequest* surfacepartrequest = (SurfacePartRequest*) request.request_data;
+
+  boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->surface->get_texture());
+
+  SDL_Rect src_rect;
+  src_rect.x = surfacepartrequest->source.x;
+  src_rect.y = surfacepartrequest->source.y;
+  src_rect.w = surfacepartrequest->size.x;
+  src_rect.h = surfacepartrequest->size.y;
+
+  SDL_Rect dst_rect;
+  dst_rect.x = request.pos.x;
+  dst_rect.y = request.pos.y;
+  dst_rect.w = surfacepartrequest->size.x;
+  dst_rect.h = surfacepartrequest->size.y;
+
+  Uint8 r = static_cast<Uint8>(request.color.red * 255);
+  Uint8 g = static_cast<Uint8>(request.color.green * 255);
+  Uint8 b = static_cast<Uint8>(request.color.blue * 255);
+  Uint8 a = static_cast<Uint8>(request.color.alpha * request.alpha * 255);
+  SDL_SetTextureColorMod(sdltexture->get_texture(), r, g, b);
+  SDL_SetTextureAlphaMod(sdltexture->get_texture(), a);
+  SDL_SetTextureBlendMode(sdltexture->get_texture(), blend2sdl(request.blend));
+
+  SDL_RendererFlip flip = SDL_FLIP_NONE;
+  if (surface->surface->get_flipx() || request.drawing_effect == HORIZONTAL_FLIP)
+  {
+    flip = SDL_FLIP_HORIZONTAL;
+  }
+  else if (request.drawing_effect == VERTICAL_FLIP)
+  {
+    flip = SDL_FLIP_VERTICAL;
+  }
+
+  SDL_RenderCopyEx(renderer, sdltexture->get_texture(), &src_rect, &dst_rect, request.angle, NULL, flip);
+}
+
+void
+SDLPainter::draw_gradient(SDL_Renderer* renderer, const DrawingRequest& request)
+{
+  const GradientRequest* gradientrequest 
+    = (GradientRequest*) request.request_data;
+  const Color& top = gradientrequest->top;
+  const Color& bottom = gradientrequest->bottom;
+
+  // calculate the maximum number of steps needed for the gradient
+  int n = static_cast<int>(std::max(std::max(fabsf(top.red - bottom.red),
+                                             fabsf(top.green - bottom.green)),
+                                    std::max(fabsf(top.blue - bottom.blue),
+                                             fabsf(top.alpha - bottom.alpha))) * 255);
+  for(int i = 0; i < n; ++i)
+  {
+    SDL_Rect rect;
+    rect.x = 0;
+    rect.y = SCREEN_HEIGHT * i / n;
+    rect.w = SCREEN_WIDTH;
+    rect.h = (SCREEN_HEIGHT * (i+1) / n) - rect.y;
+
+    float p = static_cast<float>(i+1) / static_cast<float>(n);
+    Uint8 r = static_cast<Uint8>(((1.0f - p) * top.red + p * bottom.red)  * 255);
+    Uint8 g = static_cast<Uint8>(((1.0f - p) * top.green + p * bottom.green) * 255);
+    Uint8 b = static_cast<Uint8>(((1.0f - p) * top.blue + p * bottom.blue) * 255);
+    Uint8 a = static_cast<Uint8>(((1.0f - p) * top.alpha + p * bottom.alpha) * 255);
+
+    SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
+    SDL_SetRenderDrawColor(renderer, r, g, b, a);
+    SDL_RenderFillRect(renderer, &rect);
+  }
+}
+
+void
+SDLPainter::draw_filled_rect(SDL_Renderer* renderer, const DrawingRequest& request)
+{
+  const FillRectRequest* fillrectrequest
+    = (FillRectRequest*) request.request_data;
+
+  SDL_Rect rect;
+  rect.x = request.pos.x;
+  rect.y = request.pos.y;
+  rect.w = fillrectrequest->size.x;
+  rect.h = fillrectrequest->size.y;
+
+  Uint8 r = static_cast<Uint8>(fillrectrequest->color.red * 255);
+  Uint8 g = static_cast<Uint8>(fillrectrequest->color.green * 255);
+  Uint8 b = static_cast<Uint8>(fillrectrequest->color.blue * 255);
+  Uint8 a = static_cast<Uint8>(fillrectrequest->color.alpha * 255);
+
+  int radius = std::min(std::min(rect.h / 2, rect.w / 2),
+                        static_cast<int>(fillrectrequest->radius));
+
+  if (radius)
+  {
+    int slices = radius;
+
+    // rounded top and bottom parts
+    std::vector<SDL_Rect> rects;
+    rects.reserve(2*slices + 1);
+    for(int i = 0; i < slices; ++i)
+    {
+      float p = (static_cast<float>(i) + 0.5f) / static_cast<float>(slices);
+      int xoff = radius - static_cast<int>(sqrtf(1.0f - p*p) * radius);
+
+      SDL_Rect tmp;
+      tmp.x = rect.x + xoff;
+      tmp.y = rect.y + (radius - i);
+      tmp.w = rect.w - 2*(xoff);
+      tmp.h = 1;
+      rects.push_back(tmp);
+
+      SDL_Rect tmp2;
+      tmp2.x = rect.x + xoff;
+      tmp2.y = rect.y + rect.h - radius + i;
+      tmp2.w = rect.w - 2*xoff;
+      tmp2.h = 1;
+
+      if (tmp2.y != tmp.y)
+      {
+        rects.push_back(tmp2);
+      }
+    }
+
+    if (2*radius < rect.h)
+    {
+      // center rectangle
+      SDL_Rect tmp;
+      tmp.x = rect.x;
+      tmp.y = rect.y + radius + 1;
+      tmp.w = rect.w;
+      tmp.h = rect.h - 2*radius - 1;
+      rects.push_back(tmp);
+    }
+
+    SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
+    SDL_SetRenderDrawColor(renderer, r, g, b, a);
+    SDL_RenderFillRects(renderer, &*rects.begin(), rects.size());
+  }
+  else
+  {
+    if((rect.w != 0) && (rect.h != 0))
+    {
+      SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
+      SDL_SetRenderDrawColor(renderer, r, g, b, a);
+      SDL_RenderFillRect(renderer, &rect);
+    }
+  }
+}
+
+void
+SDLPainter::draw_inverse_ellipse(SDL_Renderer* renderer, const DrawingRequest& request)
+{
+  const InverseEllipseRequest* ellipse = (InverseEllipseRequest*)request.request_data;
+  
+  float x = request.pos.x;
+  float w = ellipse->size.x;
+  float h = ellipse->size.y;
+
+  int top = request.pos.y - (h / 2);
+
+  const int max_slices = 256;
+  SDL_Rect rects[2*max_slices+2];
+  int slices = std::min(static_cast<int>(ellipse->size.y), max_slices);
+  for(int i = 0; i < slices; ++i)
+  {
+    float p = ((static_cast<float>(i) + 0.5f) / static_cast<float>(slices)) * 2.0f - 1.0f; 
+    int xoff = static_cast<int>(sqrtf(1.0f - p*p) * w / 2);
+
+    SDL_Rect& left  = rects[2*i+0];
+    SDL_Rect& right = rects[2*i+1];
+
+    left.x = 0;
+    left.y = top + (i * h / slices);
+    left.w = x - xoff;
+    left.h = (top + ((i+1) * h / slices)) - left.y;
+
+    right.x = x + xoff;
+    right.y = left.y;
+    right.w = SCREEN_WIDTH - right.x;
+    right.h = left.h;
+  }
+
+  SDL_Rect& top_rect = rects[2*slices+0];
+  SDL_Rect& bottom_rect = rects[2*slices+1];
+
+  top_rect.x = 0;
+  top_rect.y = 0;
+  top_rect.w = SCREEN_WIDTH;
+  top_rect.h = top;
+
+  bottom_rect.x = 0;
+  bottom_rect.y = top + h;
+  bottom_rect.w = SCREEN_WIDTH;
+  bottom_rect.h = SCREEN_HEIGHT - bottom_rect.y;
+
+  Uint8 r = static_cast<Uint8>(ellipse->color.red * 255);
+  Uint8 g = static_cast<Uint8>(ellipse->color.green * 255);
+  Uint8 b = static_cast<Uint8>(ellipse->color.blue * 255);
+  Uint8 a = static_cast<Uint8>(ellipse->color.alpha * 255);
+
+  SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
+  SDL_SetRenderDrawColor(renderer, r, g, b, a);
+  SDL_RenderFillRects(renderer, rects, 2*slices+2);
+}
+
+/* EOF */
diff --git a/src/video/sdl/sdl_painter.hpp b/src/video/sdl/sdl_painter.hpp
new file mode 100644 (file)
index 0000000..db31716
--- /dev/null
@@ -0,0 +1,39 @@
+//  SuperTux
+//  Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
+//
+//  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
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HEADER_SUPERTUX_VIDEO_SDL_PAINTER_HPP
+#define HEADER_SUPERTUX_VIDEO_SDL_PAINTER_HPP
+
+#include "SDL.h"
+#include "video/renderer.hpp"
+
+class SDLPainter
+{
+public:
+  static void draw_surface(SDL_Renderer* renderer, const DrawingRequest& request);
+  static void draw_surface_part(SDL_Renderer* renderer, const DrawingRequest& request);
+  static void draw_gradient(SDL_Renderer* renderer, const DrawingRequest& request);
+  static void draw_filled_rect(SDL_Renderer* renderer, const DrawingRequest& request);
+  static void draw_inverse_ellipse(SDL_Renderer* renderer, const DrawingRequest& request);
+
+private:
+  SDLPainter(const SDLPainter&);
+  SDLPainter& operator=(const SDLPainter&);
+};
+
+#endif
+
+/* EOF */
index 10b48c3..3ba6f80 100644 (file)
@@ -1,5 +1,6 @@
 //  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 "video/sdl/sdl_renderer.hpp"
 
+#include "util/log.hpp"
 #include "video/drawing_request.hpp"
 #include "video/sdl/sdl_surface_data.hpp"
 #include "video/sdl/sdl_texture.hpp"
+#include "video/sdl/sdl_painter.hpp"
 
 #include <iomanip>
 #include <iostream>
 #include <physfs.h>
 #include <sstream>
 #include <stdexcept>
+#include "SDL2/SDL_video.h"
 
-namespace {
+#include "video/util.hpp"
 
-SDL_Surface *apply_alpha(SDL_Surface *src, float alpha_factor)
+SDLRenderer::SDLRenderer() :
+  window(),
+  renderer(),
+  viewport(),
+  desktop_size(0, 0)
 {
-  // FIXME: This is really slow
-  assert(src->format->Amask);
-  int alpha = (int) (alpha_factor * 256);
-  SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
-  int bpp = dst->format->BytesPerPixel;
-  if(SDL_MUSTLOCK(src))
-  {
-    SDL_LockSurface(src);
-  }
-  if(SDL_MUSTLOCK(dst))
+  Renderer::instance_ = this;
+
+  SDL_DisplayMode mode;
+  if (SDL_GetDesktopDisplayMode(0, &mode) != 0)
   {
-    SDL_LockSurface(dst);
+    log_warning << "Couldn't get desktop display mode: " << SDL_GetError() << std::endl;
   }
-  for(int y = 0;y < dst->h;y++) {
-    for(int x = 0;x < dst->w;x++) {
-      Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
-      Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
-      Uint32 mapped = 0;
-      switch(bpp) {
-        case 1:
-          mapped = *srcpixel;
-          break;
-        case 2:
-          mapped = *(Uint16 *)srcpixel;
-          break;
-        case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-          mapped |= srcpixel[0] << 16;
-          mapped |= srcpixel[1] << 8;
-          mapped |= srcpixel[2] << 0;
-#else
-          mapped |= srcpixel[0] << 0;
-          mapped |= srcpixel[1] << 8;
-          mapped |= srcpixel[2] << 16;
-#endif
-          break;
-        case 4:
-          mapped = *(Uint32 *)srcpixel;
-          break;
-      }
-      Uint8 r, g, b, a;
-      SDL_GetRGBA(mapped, src->format, &r, &g, &b, &a);
-      mapped = SDL_MapRGBA(dst->format, r, g, b, (a * alpha) >> 8);
-      switch(bpp) {
-        case 1:
-          *dstpixel = mapped;
-          break;
-        case 2:
-          *(Uint16 *)dstpixel = mapped;
-          break;
-        case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-          dstpixel[0] = (mapped >> 16) & 0xff;
-          dstpixel[1] = (mapped >> 8) & 0xff;
-          dstpixel[2] = (mapped >> 0) & 0xff;
-#else
-          dstpixel[0] = (mapped >> 0) & 0xff;
-          dstpixel[1] = (mapped >> 8) & 0xff;
-          dstpixel[2] = (mapped >> 16) & 0xff;
-#endif
-          break;
-        case 4:
-          *(Uint32 *)dstpixel = mapped;
-          break;
-      }
-    }
-  }
-  if(SDL_MUSTLOCK(dst))
+  else
   {
-    SDL_UnlockSurface(dst);
+    desktop_size = Size(mode.w, mode.h);
   }
-  if(SDL_MUSTLOCK(src))
+
+  log_info << "creating SDLRenderer" << std::endl;
+  int width  = g_config->window_size.width;
+  int height = g_config->window_size.height;
+
+  int flags = SDL_WINDOW_RESIZABLE;
+  if(g_config->use_fullscreen)
   {
-    SDL_UnlockSurface(src);
+    flags |= SDL_WINDOW_FULLSCREEN;
+    width  = g_config->fullscreen_size.width;
+    height = g_config->fullscreen_size.height;
   }
-  return dst;
-}
 
-} // namespace
+  SCREEN_WIDTH = width;
+  SCREEN_HEIGHT = height;
 
-SDLRenderer::SDLRenderer() :
-  screen(),
-  numerator(),
-  denominator()
-{
-  Renderer::instance_ = this;
+  viewport.x = 0;
+  viewport.y = 0;
+  viewport.w = width;
+  viewport.h = height;
 
-  const SDL_VideoInfo *info = SDL_GetVideoInfo();
-  log_info << "Hardware surfaces are " << (info->hw_available ? "" : "not ") << "available." << std::endl;
-  log_info << "Hardware to hardware blits are " << (info->blit_hw ? "" : "not ") << "accelerated." << std::endl;
-  log_info << "Hardware to hardware blits with colorkey are " << (info->blit_hw_CC ? "" : "not ") << "accelerated." << std::endl;
-  log_info << "Hardware to hardware blits with alpha are " << (info->blit_hw_A ? "" : "not ") << "accelerated." << std::endl;
-  log_info << "Software to hardware blits are " << (info->blit_sw ? "" : "not ") << "accelerated." << std::endl;
-  log_info << "Software to hardware blits with colorkey are " << (info->blit_sw_CC ? "" : "not ") << "accelerated." << std::endl;
-  log_info << "Software to hardware blits with alpha are " << (info->blit_sw_A ? "" : "not ") << "accelerated." << std::endl;
-  log_info << "Color fills are " << (info->blit_fill ? "" : "not ") << "accelerated." << std::endl;
-
-  int flags = SDL_HWSURFACE | SDL_ANYFORMAT;
-  if(g_config->use_fullscreen)
-    flags |= SDL_FULLSCREEN;
-    
-  int width  = 800; //FIXME: config->screenwidth;
-  int height = 600; //FIXME: config->screenheight;
+  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
+
+  int ret = SDL_CreateWindowAndRenderer(width, height, flags,
+                                        &window, &renderer);
 
-  screen = SDL_SetVideoMode(width, height, 0, flags);
-  if(screen == 0) {
+  if(ret != 0) {
     std::stringstream msg;
     msg << "Couldn't set video mode (" << width << "x" << height
         << "): " << SDL_GetError();
     throw std::runtime_error(msg.str());
   }
 
-  numerator   = 1;
-  denominator = 1;
-  /* FIXME: 
-     float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
-     float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
-     if(xfactor < yfactor)
-     {
-     numerator = config->screenwidth;
-     denominator = SCREEN_WIDTH;
-     }
-     else
-     {
-     numerator = config->screenheight;
-     denominator = SCREEN_HEIGHT;
-     }
-  */
+  SDL_RendererInfo info;
+  if (SDL_GetRendererInfo(renderer, &info) != 0)
+  {
+    log_warning << "Couldn't get RendererInfo: " << SDL_GetError() << std::endl;
+  }
+  else
+  {
+    log_info << "SDL_Renderer: " << info.name << std::endl;
+    log_info << "SDL_RendererFlags: " << std::endl;
+    if (info.flags & SDL_RENDERER_SOFTWARE) log_info << "  SDL_RENDERER_SOFTWARE" << std::endl;
+    if (info.flags & SDL_RENDERER_ACCELERATED) log_info << "  SDL_RENDERER_ACCELERATED" << std::endl;
+    if (info.flags & SDL_RENDERER_PRESENTVSYNC) log_info << "  SDL_RENDERER_PRESENTVSYNC" << std::endl;
+    if (info.flags & SDL_RENDERER_TARGETTEXTURE) log_info << "  SDL_RENDERER_TARGETTEXTURE" << std::endl;
+    log_info << "Texture Formats: " << std::endl;
+    for(size_t i = 0; i < info.num_texture_formats; ++i)
+    {
+      log_info << "  " << SDL_GetPixelFormatName(info.texture_formats[i]) << std::endl;
+    }
+    log_info << "Max Texture Width: " << info.max_texture_width << std::endl;
+    log_info << "Max Texture Height: " << info.max_texture_height << std::endl;
+  }
+
   if(texture_manager == 0)
     texture_manager = new TextureManager();
+
+  g_config->window_size = Size(width, height);
+  apply_config();
 }
 
 SDLRenderer::~SDLRenderer()
 {
+  SDL_DestroyRenderer(renderer);
+  SDL_DestroyWindow(window);
 }
 
 void
 SDLRenderer::draw_surface(const DrawingRequest& request)
 {
-  //FIXME: support parameters request.alpha, request.angle, request.blend
-  const Surface* surface = (const Surface*) request.request_data;
-  boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->get_texture());
-  SDLSurfaceData *surface_data = reinterpret_cast<SDLSurfaceData *>(surface->get_surface_data());
+  SDLPainter::draw_surface(renderer, request);
+}
 
-  DrawingEffect effect = request.drawing_effect;
-  if (surface->get_flipx()) effect = HORIZONTAL_FLIP;
+void
+SDLRenderer::draw_surface_part(const DrawingRequest& request)
+{
+  SDLPainter::draw_surface_part(renderer, request);
+}
 
-  SDL_Surface *transform = sdltexture->get_transform(request.color, effect);
+void
+SDLRenderer::draw_gradient(const DrawingRequest& request)
+{
+  SDLPainter::draw_gradient(renderer, request);
+}
 
-  // get and check SDL_Surface
-  if (transform == 0) {
-    std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
-    return;
-  }
+void
+SDLRenderer::draw_filled_rect(const DrawingRequest& request)
+{
+  SDLPainter::draw_filled_rect(renderer, request);
+}
 
-  SDL_Rect *src_rect = surface_data->get_src_rect(effect);
-  SDL_Rect dst_rect;
-  dst_rect.x = (int) request.pos.x * numerator / denominator;
-  dst_rect.y = (int) request.pos.y * numerator / denominator;
+void
+SDLRenderer::draw_inverse_ellipse(const DrawingRequest& request)
+{
+  SDLPainter::draw_inverse_ellipse(renderer, request);
+}
 
-  Uint8 alpha = 0;
-  if(request.alpha != 1.0)
+void
+SDLRenderer::do_take_screenshot()
+{
+  // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
+  int width;
+  int height;
+  if (SDL_GetRendererOutputSize(renderer, &width, &height) != 0)
   {
-    if(!transform->format->Amask)
-    {
-      if(transform->flags & SDL_SRCALPHA)
-      {
-        alpha = transform->format->alpha;
-      }
-      else
-      {
-        alpha = 255;
-      }
-      SDL_SetAlpha(transform, SDL_SRCALPHA, (Uint8) (request.alpha * alpha));
-    }
-    /*else
-      {
-      transform = apply_alpha(transform, request.alpha);
-      }*/
+    log_warning << "SDL_GetRenderOutputSize failed: " << SDL_GetError() << std::endl;
   }
-
-  SDL_BlitSurface(transform, src_rect, screen, &dst_rect);
-
-  if(request.alpha != 1.0)
+  else
   {
-    if(!transform->format->Amask)
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+    Uint32 rmask = 0xff000000;
+    Uint32 gmask = 0x00ff0000;
+    Uint32 bmask = 0x0000ff00;
+    Uint32 amask = 0x000000ff;
+#else
+    Uint32 rmask = 0x000000ff;
+    Uint32 gmask = 0x0000ff00;
+    Uint32 bmask = 0x00ff0000;
+    Uint32 amask = 0xff000000;
+#endif
+    SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, 32,
+                                                rmask, gmask, bmask, amask);
+    if (!surface)
     {
-      if(alpha == 255)
+      log_warning << "SDL_CreateRGBSurface failed: " << SDL_GetError() << std::endl;
+    }
+    else
+    {
+      int ret = SDL_RenderReadPixels(renderer, NULL,
+                                     SDL_PIXELFORMAT_ABGR8888,
+                                     surface->pixels,
+                                     surface->pitch);
+      if (ret != 0)
       {
-        SDL_SetAlpha(transform, SDL_RLEACCEL, 0);
+        log_warning << "SDL_RenderReadPixels failed: " << SDL_GetError() << std::endl;
       }
       else
       {
-        SDL_SetAlpha(transform, SDL_SRCALPHA | SDL_RLEACCEL, alpha);
+        // 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(surface, fullFilename.c_str());
+            log_debug << "Wrote screenshot to \"" << fullFilename << "\"" << std::endl;
+            return;
+          }
+        }
+        log_warning << "Did not save screenshot, because all files up to \"" << fullFilename << "\" already existed" << std::endl;
       }
     }
-    /*else
-      {
-      SDL_FreeSurface(transform);
-      }*/
   }
 }
 
 void
-SDLRenderer::draw_surface_part(const DrawingRequest& request)
+SDLRenderer::flip()
 {
-  const SurfacePartRequest* surfacepartrequest
-    = (SurfacePartRequest*) request.request_data;
-
-  const Surface* surface = surfacepartrequest->surface;
-  boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->get_texture());
-
-  DrawingEffect effect = request.drawing_effect;
-  if (surface->get_flipx()) effect = HORIZONTAL_FLIP;
+  SDL_RenderPresent(renderer);
+}
 
-  SDL_Surface *transform = sdltexture->get_transform(request.color, effect);
+void
+SDLRenderer::resize(int w , int h)
+{
+  g_config->window_size = Size(w, h);
 
-  // get and check SDL_Surface
-  if (transform == 0) {
-    std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
-    return;
-  }
+  apply_config();
+}
 
-  int ox, oy;
-  if (effect == HORIZONTAL_FLIP)
-  {
-    ox = sdltexture->get_texture_width() - surface->get_x() - (int) surfacepartrequest->size.x;
-  }
-  else
-  {
-    ox = surface->get_x();
-  }
-  if (effect == VERTICAL_FLIP)
+void
+SDLRenderer::apply_video_mode()
+{
+  if (!g_config->use_fullscreen)
   {
-    oy = sdltexture->get_texture_height() - surface->get_y() - (int) surfacepartrequest->size.y;
+    SDL_SetWindowFullscreen(window, 0);
   }
   else
   {
-    oy = surface->get_y();
-  }
-
-  SDL_Rect src_rect;
-  src_rect.x = (ox + (int) surfacepartrequest->source.x) * numerator / denominator;
-  src_rect.y = (oy + (int) surfacepartrequest->source.y) * numerator / denominator;
-  src_rect.w = (int) surfacepartrequest->size.x * numerator / denominator;
-  src_rect.h = (int) surfacepartrequest->size.y * numerator / denominator;
-
-  SDL_Rect dst_rect;
-  dst_rect.x = (int) request.pos.x * numerator / denominator;
-  dst_rect.y = (int) request.pos.y * numerator / denominator;
-
-  Uint8 alpha = 0;
-  if(request.alpha != 1.0)
-  {
-    if(!transform->format->Amask)
+    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)
     {
-      if(transform->flags & SDL_SRCALPHA)
-      {
-        alpha = transform->format->alpha;
-      }
-      else
-      {
-        alpha = 255;
-      }
-      SDL_SetAlpha(transform, SDL_SRCALPHA, (Uint8) (request.alpha * alpha));
+      log_warning << "failed to set display mode: "
+                  << mode.w << "x" << mode.h << "@" << mode.refresh_rate << ": "
+                  << SDL_GetError() << std::endl;
     }
-    /*else
-      {
-      transform = apply_alpha(transform, request.alpha);
-      }*/
-  }
-
-  SDL_BlitSurface(transform, &src_rect, screen, &dst_rect);
-
-  if(request.alpha != 1.0)
-  {
-    if(!transform->format->Amask)
+    else
     {
-      if(alpha == 255)
+      if (SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN) != 0)
       {
-        SDL_SetAlpha(transform, SDL_RLEACCEL, 0);
+        log_warning << "failed to switch to fullscreen mode: "
+                    << mode.w << "x" << mode.h << "@" << mode.refresh_rate << ": "
+                    << SDL_GetError() << std::endl;
       }
       else
       {
-        SDL_SetAlpha(transform, SDL_SRCALPHA | SDL_RLEACCEL, alpha);
+        log_info << "switched to fullscreen mode: "
+                 << mode.w << "x" << mode.h << "@" << mode.refresh_rate << std::endl;
       }
     }
-    /*else
-      {
-      SDL_FreeSurface(transform);
-      }*/
   }
+
 }
 
 void
-SDLRenderer::draw_gradient(const DrawingRequest& request)
+SDLRenderer::apply_viewport()
 {
-  const GradientRequest* gradientrequest 
-    = (GradientRequest*) request.request_data;
-  const Color& top = gradientrequest->top;
-  const Color& bottom = gradientrequest->bottom;
+  Size target_size = g_config->use_fullscreen ?
+    g_config->fullscreen_size :
+    g_config->window_size;
 
-  for(int y = 0;y < screen->h;++y)
+  float pixel_aspect_ratio = 1.0f;
+  if (g_config->aspect_size != Size(0, 0))
   {
-    Uint8 r = (Uint8)((((float)(top.red-bottom.red)/(0-screen->h)) * y + top.red) * 255);
-    Uint8 g = (Uint8)((((float)(top.green-bottom.green)/(0-screen->h)) * y + top.green) * 255);
-    Uint8 b = (Uint8)((((float)(top.blue-bottom.blue)/(0-screen->h)) * y + top.blue) * 255);
-    Uint8 a = (Uint8)((((float)(top.alpha-bottom.alpha)/(0-screen->h)) * y + top.alpha) * 255);
-    Uint32 color = SDL_MapRGB(screen->format, r, g, b);
-
-    SDL_Rect rect;
-    rect.x = 0;
-    rect.y = y;
-    rect.w = screen->w;
-    rect.h = 1;
-
-    if(a == SDL_ALPHA_OPAQUE) {
-      SDL_FillRect(screen, &rect, color);
-    } else if(a != SDL_ALPHA_TRANSPARENT) {
-      SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
-
-      SDL_FillRect(temp, 0, color);
-      SDL_SetAlpha(temp, SDL_SRCALPHA | SDL_RLEACCEL, a);
-      SDL_BlitSurface(temp, 0, screen, &rect);
-      SDL_FreeSurface(temp);
-    }
-  }
-}
-
-void
-SDLRenderer::draw_filled_rect(const DrawingRequest& request)
-{
-  const FillRectRequest* fillrectrequest
-    = (FillRectRequest*) request.request_data;
-
-  SDL_Rect rect;
-  rect.x = (Sint16)request.pos.x * screen->w / SCREEN_WIDTH;
-  rect.y = (Sint16)request.pos.y * screen->h / SCREEN_HEIGHT;
-  rect.w = (Uint16)fillrectrequest->size.x * screen->w / SCREEN_WIDTH;
-  rect.h = (Uint16)fillrectrequest->size.y * screen->h / SCREEN_HEIGHT;
-  if((rect.w == 0) || (rect.h == 0)) {
-    return;
+    pixel_aspect_ratio = calculate_pixel_aspect_ratio(desktop_size,
+                                                      g_config->aspect_size);
   }
-  Uint8 r = static_cast<Uint8>(fillrectrequest->color.red * 255);
-  Uint8 g = static_cast<Uint8>(fillrectrequest->color.green * 255);
-  Uint8 b = static_cast<Uint8>(fillrectrequest->color.blue * 255);
-  Uint8 a = static_cast<Uint8>(fillrectrequest->color.alpha * 255);
-  Uint32 color = SDL_MapRGB(screen->format, r, g, b);
-  if(a == SDL_ALPHA_OPAQUE) {
-    SDL_FillRect(screen, &rect, color);
-  } else if(a != SDL_ALPHA_TRANSPARENT) {
-    SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
-
-    SDL_FillRect(temp, 0, color);
-    SDL_SetAlpha(temp, SDL_SRCALPHA | SDL_RLEACCEL, a);
-    SDL_BlitSurface(temp, 0, screen, &rect);
-    SDL_FreeSurface(temp);
+  else if (g_config->use_fullscreen)
+  {
+    pixel_aspect_ratio = calculate_pixel_aspect_ratio(desktop_size,
+                                                      target_size);
   }
-}
 
-void
-SDLRenderer::draw_inverse_ellipse(const DrawingRequest&)
-{
-}
+  // calculate the viewport
+  Size max_size(1280, 800);
+  Size min_size(640, 480);
 
-void 
-SDLRenderer::do_take_screenshot()
-{
-  // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
+  Vector scale;
+  Size logical_size;
+  calculate_viewport(min_size, max_size,
+                     target_size,
+                     pixel_aspect_ratio,
+                     g_config->magnification,
+                     scale, logical_size, viewport);
 
-  SDL_Surface *screen = SDL_GetVideoSurface();
-
-  // 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(screen, fullFilename.c_str());
-      log_debug << "Wrote screenshot to \"" << fullFilename << "\"" << std::endl;
-      return;
-    }
+  SCREEN_WIDTH = logical_size.width;
+  SCREEN_HEIGHT = logical_size.height;
+
+  if (viewport.x != 0 || viewport.y != 0)
+  {
+    // Clear the screen to avoid garbage in unreachable areas after we
+    // reset the coordinate system
+    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
+    SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
+    SDL_RenderClear(renderer);
+    SDL_RenderPresent(renderer);
+    SDL_RenderClear(renderer);
   }
-  log_warning << "Did not save screenshot, because all files up to \"" << fullFilename << "\" already existed" << std::endl;
+
+  SDL_RenderSetScale(renderer, 1.0f, 1.0f);
+  SDL_RenderSetViewport(renderer, &viewport);
+  SDL_RenderSetScale(renderer, scale.x, scale.y);
 }
 
 void
-SDLRenderer::flip()
+SDLRenderer::apply_config()
+{
+  apply_video_mode();
+  apply_viewport();
+}
+
+Vector
+SDLRenderer::to_logical(int physical_x, int physical_y)
 {
-  SDL_Flip(screen);
+  return Vector(static_cast<float>(physical_x - viewport.x) * SCREEN_WIDTH / viewport.w,
+                static_cast<float>(physical_y - viewport.y) * SCREEN_HEIGHT / viewport.h);
 }
 
 void
-SDLRenderer::resize(int, int)
+SDLRenderer::set_gamma(float gamma)
 {
-    
+  Uint16 ramp[256];
+  SDL_CalculateGammaRamp(gamma, ramp);
+  SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
 }
 
 /* EOF */
index 7f78180..0206e84 100644 (file)
@@ -17,8 +17,7 @@
 #ifndef HEADER_SUPERTUX_VIDEO_SDL_RENDERER_HPP
 #define HEADER_SUPERTUX_VIDEO_SDL_RENDERER_HPP
 
-#include <SDL_video.h>
-
+#include "SDL.h"
 #include "video/renderer.hpp"
 
 class SDLRenderer : public Renderer
@@ -29,19 +28,27 @@ public:
 
   void draw_surface(const DrawingRequest& request);
   void draw_surface_part(const DrawingRequest& request);
-  void draw_text(const DrawingRequest& request);
   void draw_gradient(const DrawingRequest& request);
   void draw_filled_rect(const DrawingRequest& request);
   void draw_inverse_ellipse(const DrawingRequest& request);
   void do_take_screenshot();
   void flip();
   void resize(int w, int h);
-  void apply_config() {}
+  void apply_config();
+  Vector to_logical(int physical_x, int physical_y);
+  void set_gamma(float gamma);
+  SDL_Window* get_window() const { return window; }
+  SDL_Renderer* get_sdl_renderer() const { return renderer; };
+
+private:
+  void apply_video_mode();
+  void apply_viewport();
 
 private:
-  SDL_Surface *screen;
-  int numerator;
-  int denominator;
+  SDL_Window* window;
+  SDL_Renderer* renderer;
+  SDL_Rect viewport;
+  Size desktop_size;
 
 private:
   SDLRenderer(const SDLRenderer&);
index b58f7cc..6093e3d 100644 (file)
@@ -20,6 +20,7 @@
 #include "supertux/globals.hpp"
 #include "video/color.hpp"
 #include "video/sdl/sdl_texture.hpp"
+#include "video/sdl/sdl_renderer.hpp"
 #include "util/log.hpp"
 #include "math/random_generator.hpp"
 
 
 #include <SDL.h>
 
-namespace {
-#define BILINEAR
-
-static Uint32 get_pixel_mapping (SDL_Surface *src, void *pixel)
-{
-  Uint32 mapped = 0;
-
-  switch (src->format->BytesPerPixel)
-  {
-    case 1:
-      mapped = *((Uint8 *) pixel);
-      break;
-    case 2:
-      mapped = *((Uint16 *) pixel);
-      break;
-    case 3:
-    {
-      Uint8 *tmp = (Uint8 *) pixel;
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-      mapped |= tmp[0] << 16;
-      mapped |= tmp[1] << 8;
-      mapped |= tmp[2] << 0;
-#else
-      mapped |= tmp[0] << 0;
-      mapped |= tmp[1] << 8;
-      mapped |= tmp[2] << 16;
-#endif
-      break;
-    }
-    case 4:
-      mapped = *((Uint32 *) pixel);
-      break;
-
-    default:
-      log_warning << "Unknown BytesPerPixel value: "
-        << src->format->BytesPerPixel << std::endl;
-      mapped = 0;
-  } /* switch (bpp) */
-
-  return (mapped);
-} /* Uint32 get_pixel_mapping */
-
-static Uint32 get_random_color (SDL_Surface *src)
-{
-  Uint32 r;
-
-  r = (Uint32) graphicsRandom.rand ();
-  /* rand() returns 31bit random numbers. So call it twice to get full 32 bit. */
-  r <<= 1;
-  r |= (Uint32) graphicsRandom.rand ();
-
-  switch (src->format->BytesPerPixel)
-  {
-    case 1:
-      r &= 0x000000ff;
-      break;
-
-    case 2:
-      r &= 0x0000ffff;
-      break;
-
-    case 3:
-      r &= 0x0000ffff;
-      break;
-  }
-
-  return (r);
-} /* Uint32 get_random_color */
-
-static bool color_is_used (SDL_Surface *src, Uint32 color)
-{
-  if(SDL_MUSTLOCK(src))
-    SDL_LockSurface(src);
-
-  for(int y = 0; y < src->h; y++) {
-    for(int x = 0; x < src->w; x++) {
-      Uint8 *pixel = (Uint8 *) src->pixels
-        + (y * src->pitch) + (x * src->format->BytesPerPixel);
-      Uint32 mapped = get_pixel_mapping (src, pixel);
-
-      if (color == mapped)
-        return (true);
-    }
-  }
-
-  return (false);
-} /* bool color_is_used */
-
-static Uint32 get_unused_color (SDL_Surface *src)
-{
-  Uint32 random_color;
-
-  do
-  {
-    random_color = get_random_color (src);
-  } while (color_is_used (src, random_color));
-
-  return (random_color);
-} /* Uint32 get_unused_color */
-
-#ifdef NAIVE
-SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
-{
-  if(numerator == denominator)
-  {
-    src->refcount++;
-    return src;
-  }
-  else
-  {
-    SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
-    int bpp = dst->format->BytesPerPixel;
-    if(SDL_MUSTLOCK(src))
-    {
-      SDL_LockSurface(src);
-    }
-    if(SDL_MUSTLOCK(dst))
-    {
-      SDL_LockSurface(dst);
-    }
-    for(int y = 0;y < dst->h;y++) {
-      for(int x = 0;x < dst->w;x++) {
-        Uint8 *srcpixel = (Uint8 *) src->pixels + (y * denominator / numerator) * src->pitch + (x * denominator / numerator) * bpp;
-        Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
-        switch(bpp) {
-          case 4:
-            dstpixel[3] = srcpixel[3];
-          case 3:
-            dstpixel[2] = srcpixel[2];
-          case 2:
-            dstpixel[1] = srcpixel[1];
-          case 1:
-            dstpixel[0] = srcpixel[0];
-        }
-      }
-    }
-    if(SDL_MUSTLOCK(dst))
-    {
-      SDL_UnlockSurface(dst);
-    }
-    if(SDL_MUSTLOCK(src))
-    {
-      SDL_UnlockSurface(src);
-    }
-    if(!src->format->Amask)
-    {
-      if(src->flags & SDL_SRCALPHA)
-      {
-        SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha);
-      }
-      if(src->flags & SDL_SRCCOLORKEY)
-      {
-        SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey);
-      }
-    }
-    return dst;
-  }
-} // namespace
-#endif
-
-#ifdef BILINEAR
-void getpixel(SDL_Surface *src, int srcx, int srcy, Uint8 color[4])
-{
-  int bpp = src->format->BytesPerPixel;
-  if(srcx == src->w)
-  {
-    srcx--;
-  }
-  if(srcy == src->h)
-  {
-    srcy--;
-  }
-  Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
-  Uint32 mapped = get_pixel_mapping (src, srcpixel);
-  SDL_GetRGBA(mapped, src->format, &color[0], &color[1], &color[2], &color[3]);
-}
-
-void merge(Uint8 color[4], Uint8 color0[4], Uint8 color1[4], int rem, int total)
-{
-  color[0] = (color0[0] * (total - rem) + color1[0] * rem) / total;
-  color[1] = (color0[1] * (total - rem) + color1[1] * rem) / total;
-  color[2] = (color0[2] * (total - rem) + color1[2] * rem) / total;
-  color[3] = (color0[3] * (total - rem) + color1[3] * rem) / total;
-}
-
-SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
-{
-  if(numerator == denominator)
-  {
-    src->refcount++;
-    return src;
-  }
-  else
-  {
-    SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
-    int bpp = dst->format->BytesPerPixel;
-    if(SDL_MUSTLOCK(src))
-    {
-      SDL_LockSurface(src);
-    }
-    if(SDL_MUSTLOCK(dst))
-    {
-      SDL_LockSurface(dst);
-    }
-    for(int y = 0;y < dst->h;y++) {
-      for(int x = 0;x < dst->w;x++) {
-        int srcx = x * denominator / numerator;
-        int srcy = y * denominator / numerator;
-        Uint8 color00[4], color01[4], color10[4], color11[4];
-        getpixel(src, srcx, srcy, color00);
-        getpixel(src, srcx + 1, srcy, color01);
-        getpixel(src, srcx, srcy + 1, color10);
-        getpixel(src, srcx + 1, srcy + 1, color11);
-        Uint8 color0[4], color1[4], color[4];
-        int remx = x * denominator % numerator;
-        merge(color0, color00, color01, remx, numerator);
-        merge(color1, color10, color11, remx, numerator);
-        int remy = y * denominator % numerator;
-        merge(color, color0, color1, remy, numerator);
-        Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
-        Uint32 mapped = SDL_MapRGBA(dst->format, color[0], color[1], color[2], color[3]);
-        switch(bpp) {
-          case 1:
-            *dstpixel = mapped;
-            break;
-          case 2:
-            *(Uint16 *)dstpixel = mapped;
-            break;
-          case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-            dstpixel[0] = (mapped >> 16) & 0xff;
-            dstpixel[1] = (mapped >> 8) & 0xff;
-            dstpixel[2] = (mapped >> 0) & 0xff;
-#else
-            dstpixel[0] = (mapped >> 0) & 0xff;
-            dstpixel[1] = (mapped >> 8) & 0xff;
-            dstpixel[2] = (mapped >> 16) & 0xff;
-#endif
-            break;
-          case 4:
-            *(Uint32 *)dstpixel = mapped;
-            break;
-        }
-      }
-    }
-    if(SDL_MUSTLOCK(dst))
-    {
-      SDL_UnlockSurface(dst);
-    }
-    if(SDL_MUSTLOCK(src))
-    {
-      SDL_UnlockSurface(src);
-    }
-    if(!src->format->Amask)
-    {
-      if(src->flags & SDL_SRCALPHA)
-      {
-        SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha);
-      }
-      if(src->flags & SDL_SRCCOLORKEY)
-      {
-        SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey);
-      }
-    }
-    return dst;
-  }
-}
-#endif
-
-SDL_Surface *horz_flip(SDL_Surface *src)
-{
-  SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
-  int bpp = dst->format->BytesPerPixel;
-  if(SDL_MUSTLOCK(src))
-  {
-    SDL_LockSurface(src);
-  }
-  if(SDL_MUSTLOCK(dst))
-  {
-    SDL_LockSurface(dst);
-  }
-  for(int y = 0;y < dst->h;y++) {
-    for(int x = 0;x < dst->w;x++) {
-      Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
-      Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + (dst->w - x - 1) * bpp;
-      switch(bpp) {
-        case 4:
-          dstpixel[3] = srcpixel[3];
-        case 3:
-          dstpixel[2] = srcpixel[2];
-        case 2:
-          dstpixel[1] = srcpixel[1];
-        case 1:
-          dstpixel[0] = srcpixel[0];
-      }
-    }
-  }
-  if(SDL_MUSTLOCK(dst))
-  {
-    SDL_UnlockSurface(dst);
-  }
-  if(SDL_MUSTLOCK(src))
-  {
-    SDL_UnlockSurface(src);
-  }
-  if(!src->format->Amask)
-  {
-    if(src->flags & SDL_SRCALPHA)
-    {
-      SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha);
-    }
-    if(src->flags & SDL_SRCCOLORKEY)
-    {
-      SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey);
-    }
-  }
-  return dst;
-}
-
-SDL_Surface *vert_flip(SDL_Surface *src)
-{
-  SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
-  int bpp = dst->format->BytesPerPixel;
-  if(SDL_MUSTLOCK(src))
-  {
-    SDL_LockSurface(src);
-  }
-  if(SDL_MUSTLOCK(dst))
-  {
-    SDL_LockSurface(dst);
-  }
-  for(int y = 0;y < dst->h;y++) {
-    for(int x = 0;x < dst->w;x++) {
-      Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
-      Uint8 *dstpixel = (Uint8 *) dst->pixels + (dst->h - y - 1) * dst->pitch + x * bpp;
-      switch(bpp) {
-        case 4:
-          dstpixel[3] = srcpixel[3];
-        case 3:
-          dstpixel[2] = srcpixel[2];
-        case 2:
-          dstpixel[1] = srcpixel[1];
-        case 1:
-          dstpixel[0] = srcpixel[0];
-      }
-    }
-  }
-  if(SDL_MUSTLOCK(dst))
-  {
-    SDL_UnlockSurface(dst);
-  }
-  if(SDL_MUSTLOCK(src))
-  {
-    SDL_UnlockSurface(src);
-  }
-  if(!src->format->Amask)
-  {
-    if(src->flags & SDL_SRCALPHA)
-    {
-      SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha);
-    }
-    if(src->flags & SDL_SRCCOLORKEY)
-    {
-      SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey);
-    }
-  }
-  return dst;
-}
-
-SDL_Surface *colorize(SDL_Surface *src, const Color &color)
+SDLTexture::SDLTexture(SDL_Surface* image) :
+  texture()
 {
-  // FIXME: This is really slow
-  assert(color.red != 1.0 || color.green != 1.0 || color.blue != 1.0);
-  int red = (int) (color.red * 256);
-  int green = (int) (color.green * 256);
-  int blue = (int) (color.blue * 256);
-  SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
-  int bpp = dst->format->BytesPerPixel;
-  if(SDL_MUSTLOCK(src))
-  {
-    SDL_LockSurface(src);
-  }
-  if(SDL_MUSTLOCK(dst))
+  texture = SDL_CreateTextureFromSurface(static_cast<SDLRenderer*>(Renderer::instance())->get_sdl_renderer(),
+                                         image);
+  if (!texture)
   {
-    SDL_LockSurface(dst);
-  }
-  for(int y = 0;y < dst->h;y++) {
-    for(int x = 0;x < dst->w;x++) {
-      Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
-      Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
-      Uint32 mapped = 0;
-      switch(bpp) {
-        case 1:
-          mapped = *srcpixel;
-          break;
-        case 2:
-          mapped = *(Uint16 *)srcpixel;
-          break;
-        case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-          mapped |= srcpixel[0] << 16;
-          mapped |= srcpixel[1] << 8;
-          mapped |= srcpixel[2] << 0;
-#else
-          mapped |= srcpixel[0] << 0;
-          mapped |= srcpixel[1] << 8;
-          mapped |= srcpixel[2] << 16;
-#endif
-          break;
-        case 4:
-          mapped = *(Uint32 *)srcpixel;
-          break;
-      }
-      if(src->format->Amask || !(src->flags & SDL_SRCCOLORKEY) || mapped != src->format->colorkey)
-      {
-        Uint8 r, g, b, a;
-        SDL_GetRGBA(mapped, src->format, &r, &g, &b, &a);
-        mapped = SDL_MapRGBA(dst->format, (r * red) >> 8, (g * green) >> 8, (b * blue) >> 8, a);
-      }
-      switch(bpp) {
-        case 1:
-          *dstpixel = mapped;
-          break;
-        case 2:
-          *(Uint16 *)dstpixel = mapped;
-          break;
-        case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-          dstpixel[0] = (mapped >> 16) & 0xff;
-          dstpixel[1] = (mapped >> 8) & 0xff;
-          dstpixel[2] = (mapped >> 0) & 0xff;
-#else
-          dstpixel[0] = (mapped >> 0) & 0xff;
-          dstpixel[1] = (mapped >> 8) & 0xff;
-          dstpixel[2] = (mapped >> 16) & 0xff;
-#endif
-          break;
-        case 4:
-          *(Uint32 *)dstpixel = mapped;
-          break;
-      }
-    }
+    std::ostringstream msg;
+    msg << "couldn't create texture: " << SDL_GetError();
+    throw std::runtime_error(msg.str());
   }
-  if(SDL_MUSTLOCK(dst))
-  {
-    SDL_UnlockSurface(dst);
-  }
-  if(SDL_MUSTLOCK(src))
-  {
-    SDL_UnlockSurface(src);
-  }
-  if(!src->format->Amask)
-  {
-    if(src->flags & SDL_SRCALPHA)
-    {
-      SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha);
-    }
-    if(src->flags & SDL_SRCCOLORKEY)
-    {
-      SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey);
-    }
-  }
-  return dst;
-}
 
-/** Optimizes a SDL_Surface surface and returns it in the "display format". If
- *  the surface does not have an alpha channel, simply calls
- *  "SDL_DisplayFormat". If the surface has an alpha channel, examines all the
- *  pixels. If in fact semi-transparent pixels are found, calls
- *  "SDL_DisplayFormatAlpha". If only fully transparent and fully opaque pixels
- *  are found, converts the surface to a 1-bit alpha surface with
- *  "SDL_SetColorKey". */
-SDL_Surface *optimize(SDL_Surface *src)
-{
-  bool have_transparent = false;
-  bool have_semi_trans = false;
-  bool have_opaque = false;
-
-  if(!src->format->Amask)
-    return SDL_DisplayFormat(src);
-
-  if(SDL_MUSTLOCK(src))
-    SDL_LockSurface(src);
-
-  /* Iterate over all the pixels and record which ones we found. */
-  for(int y = 0; y < src->h; y++) {
-    for(int x = 0; x < src->w; x++) {
-      Uint8 *pixel = (Uint8 *) src->pixels
-        + (y * src->pitch) + (x * src->format->BytesPerPixel);
-      Uint32 mapped = get_pixel_mapping (src, pixel);
-      Uint8 red, green, blue, alpha;
-      SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
-
-      if (alpha < 16)
-        have_transparent = true;
-      else if (alpha > 240)
-        have_opaque = true;
-      else
-        have_semi_trans = true;
-    } /* for (x) */
-  } /* for (y) */
-
-  if(SDL_MUSTLOCK(src))
-    SDL_UnlockSurface(src);
-
-  if (have_semi_trans)
-    return SDL_DisplayFormatAlpha(src);
-
-  if (!have_transparent /* && !have_semi_trans */)
-    return SDL_DisplayFormat(src);
-
-  /* The surface is totally transparent. We shouldn't return a surface at all,
-   * but since the calling code can't cope with that, use the alpha channel in
-   * this case. */
-  if (!have_opaque /* && !have_semi_trans */)
-    return SDL_DisplayFormatAlpha(src);
-
-  /* If we get here, the surface has fully transparent pixels and fully opaque
-   * pixels, but no semi-transparent pixels. We can therefore use a one bit
-   * transparency, which is pretty fast to draw. This code path is a bit bulky
-   * and rarely used (~25 surfaces when starting the game and entering a
-   * level), so it could be removed for readabilities sake. -octo */
-
-  /* Create a new surface without alpha channel */
-  SDL_Surface *dst = SDL_CreateRGBSurface(src->flags & ~(SDL_SRCALPHA),
-      src->w, src->h, src->format->BitsPerPixel,
-      src->format->Rmask,  src->format->Gmask, src->format->Bmask, /* Amask = */ 0);
-  /* Get a color that's not in the source surface. It is used to mark
-   * transparent pixels. There's a possible race condition: Maybe we should
-   * lock the surface before calling this function and add a "bool have_lock"
-   * argument to "get_unused_color"? -octo */
-  Uint32 color_key = get_unused_color (src);
-
-  if(SDL_MUSTLOCK(src))
-    SDL_LockSurface(src);
-  if(SDL_MUSTLOCK(dst))
-    SDL_LockSurface(dst);
-
-  /* Copy all the pixels to the new surface */
-  for(int y = 0; y < src->h; y++) {
-    for(int x = 0; x < src->w; x++) {
-      Uint8 *src_pixel = (Uint8 *) src->pixels
-        + (y * src->pitch) + (x * src->format->BytesPerPixel);
-      Uint8 *dst_pixel = (Uint8 *) dst->pixels
-        + (y * dst->pitch) + (x * dst->format->BytesPerPixel);
-      Uint32 mapped = get_pixel_mapping (src, src_pixel);
-      Uint8 red, green, blue, alpha;
-      SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
-
-      /* "alpha" should either be smaller than 16 or greater than 240. We
-       * unlocked the surface in between though, so use 128 to play it save,
-       * i.e. don't leave any unspecified code paths. */
-      if (alpha < 128)
-        mapped = color_key;
-
-      switch (dst->format->BytesPerPixel)
-      {
-        case 1:
-          *dst_pixel = (Uint8) mapped;
-          break;
-
-        case 2:
-          *((Uint16 *) dst_pixel) = (Uint16) mapped;
-          break;
-
-        case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-            dst_pixel[0] = (mapped >> 16) & 0xff;
-            dst_pixel[1] = (mapped >> 8) & 0xff;
-            dst_pixel[2] = (mapped >> 0) & 0xff;
-#else
-            dst_pixel[0] = (mapped >> 0) & 0xff;
-            dst_pixel[1] = (mapped >> 8) & 0xff;
-            dst_pixel[2] = (mapped >> 16) & 0xff;
-#endif
-            break;
-
-        case 4:
-            *((Uint32 *) dst_pixel) = mapped;
-      } /* switch (dst->format->BytesPerPixel) */
-    } /* for (x) */
-  } /* for (y) */
-
-  if(SDL_MUSTLOCK(src))
-    SDL_UnlockSurface(src);
-  if(SDL_MUSTLOCK(dst))
-    SDL_UnlockSurface(dst);
-
-  /* Tell SDL that the "color_key" color is supposed to be transparent. */
-  SDL_SetColorKey (dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, color_key);
-  SDL_Surface *convert = SDL_DisplayFormat(dst);
-  SDL_FreeSurface(dst);
-  return convert;
-} /* SDL_Surface *optimize */
-
-} /* namespace */
-
-SDLTexture::SDLTexture(SDL_Surface* image) :
-  texture()
-{
-  texture = optimize(image);
-  //width = texture->w;
-  //height = texture->h;
-  int numerator   = 1;
-  int denominator = 1;
-  //FIXME: float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
-  //FIXME: float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
-  /* FIXME: 
-     if(xfactor < yfactor)
-     {
-     numerator = config->screenwidth;
-     denominator = SCREEN_WIDTH;
-     }
-     else
-     {
-     numerator = config->screenheight;
-     denominator = SCREEN_HEIGHT;
-     }
-  */
-  cache[NO_EFFECT][Color::WHITE] = scale(texture, numerator, denominator);
+  width = image->w;
+  height = image->h;
 }
 
 SDLTexture::~SDLTexture()
 {
-  SDL_FreeSurface(texture);
-}
-
-SDL_Surface*
-SDLTexture::get_transform(const Color &color, DrawingEffect effect)
-{
-  if(cache[NO_EFFECT][color] == 0) {
-    assert(cache[NO_EFFECT][Color::WHITE]);
-    cache[NO_EFFECT][color] = colorize(cache[NO_EFFECT][Color::WHITE], color);
-  }
-  if(cache[effect][color] == 0) {
-    assert(cache[NO_EFFECT][color]);
-    switch(effect) {
-      case NO_EFFECT:
-        break;
-      case HORIZONTAL_FLIP:
-        cache[HORIZONTAL_FLIP][color] = horz_flip(cache[NO_EFFECT][color]);
-        break;
-      case VERTICAL_FLIP:
-        cache[VERTICAL_FLIP][color] = vert_flip(cache[NO_EFFECT][color]);
-        break;
-      default:
-        return 0;
-    }
-  }
-  return cache[effect][color];
+  SDL_DestroyTexture(texture);
 }
 
 /* vim: set sw=2 sts=2 et : */
index 97c38cb..e92c316 100644 (file)
 class SDLTexture : public Texture
 {
 protected:
-  SDL_Surface *texture;
-  //unsigned int width;
-  //unsigned int height;
-
-  struct ColorCache
-  {
-    static const int HASHED_BITS = 3;
-    static const int CACHE_SIZE = 1 << (HASHED_BITS * 3);
-
-    static void ref(SDL_Surface *surface)
-    {
-      if(surface)
-      {
-        surface->refcount++;
-      }
-    }
-
-    static int hash(const Color &color)
-    {
-      return
-        ((int) (color.red * ((1 << HASHED_BITS) - 1)) << (HASHED_BITS - 1) * 2) |
-        ((int) (color.green * ((1 << HASHED_BITS) - 1)) << (HASHED_BITS - 1)) |
-        ((int) (color.blue * ((1 << HASHED_BITS) - 1)) << 0);
-    }
-
-    SDL_Surface *data[CACHE_SIZE];
-
-    ColorCache()
-    {
-      memset(data, 0, CACHE_SIZE * sizeof(SDL_Surface *));
-    }
-
-    ColorCache(const ColorCache&);
-
-    ~ColorCache()
-    {
-      std::for_each(data, data + CACHE_SIZE, SDL_FreeSurface);
-    }
-
-    ColorCache& operator=(const ColorCache &other)
-    {
-      if (this != &other)
-      {
-        std::for_each(other.data, other.data + CACHE_SIZE, ref);
-        std::for_each(data, data + CACHE_SIZE, SDL_FreeSurface);
-        memcpy(data, other.data, CACHE_SIZE * sizeof(SDL_Surface *));
-      }
-      return *this;
-    }
-
-    SDL_Surface *&operator [] (const Color &color)
-    {
-      return data[hash(color)];
-    }
-  };
-  //typedef std::map<Color, SDL_Surface *> ColorCache;
-  ColorCache cache[NUM_EFFECTS];
+  SDL_Texture* texture;
+  int width;
+  int height;
 
 public:
   SDLTexture(SDL_Surface* sdlsurface);
   virtual ~SDLTexture();
 
-  SDL_Surface *get_transform(const Color &color, DrawingEffect effect);
-
-  SDL_Surface *get_texture() const
+  SDL_Texture *get_texture() const
   {
     return texture;
   }
 
   unsigned int get_texture_width() const
   {
-    return texture->w;
+    return width;
   }
 
   unsigned int get_texture_height() const
   {
-    return texture->h;
+    return height;
   }
 
   unsigned int get_image_width() const
   {
-    return texture->w;
+    return width;
   }
 
   unsigned int get_image_height() const
   {
-    return texture->h;
-  }
-
-  /*unsigned int get_texture_width() const
-    {
-    return width;
-    }
-
-    unsigned int get_texture_height() const
-    {
     return height;
-    }
-
-    unsigned int get_image_width() const
-    {
-    return width;
-    }
-
-    unsigned int get_image_height() const
-    {
-    return height;
-    }*/
+  }
 
 private:
   SDLTexture(const SDLTexture&);
index 7e07d77..7be9a09 100644 (file)
@@ -158,10 +158,10 @@ TextureManager::create_image_texture_raw(const std::string& filename, const Rect
     throw std::runtime_error("SDL_CreateRGBSurfaceFrom() call failed");
   }
 
-  if (image->format->palette)
/* if (image->format->palette)
   { // copy the image palette to subimage if present
-    SDL_SetColors(subimage.get(), image->format->palette->colors, 0, image->format->palette->ncolors);
-  }
+    SDL_SetSurfacePalette(subimage.get(), image->format->palette->colors); //edited by giby 
+  } */
 
   return VideoSystem::new_texture(subimage.get());
 }
diff --git a/src/video/util.cpp b/src/video/util.cpp
new file mode 100644 (file)
index 0000000..294ed2d
--- /dev/null
@@ -0,0 +1,148 @@
+//  SuperTux
+//  Copyright (C) 2014 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "video/util.hpp"
+
+#include <algorithm>
+
+#include "math/size.hpp"
+#include "math/vector.hpp"
+
+namespace {
+
+inline Size
+apply_pixel_aspect_ratio_pre(const Size& window_size, float pixel_aspect_ratio)
+{
+  if (true)
+  {
+    return Size(window_size.width * pixel_aspect_ratio,
+                window_size.height);
+  }
+  else
+  {
+    return Size(window_size.width,
+                window_size.height * pixel_aspect_ratio);
+  }
+}
+
+inline void
+apply_pixel_aspect_ratio_post(const Size& real_window_size, const Size& window_size, float scale,
+                                   SDL_Rect& out_viewport, Vector& out_scale)
+{
+  Vector transform(static_cast<float>(real_window_size.width) / window_size.width,
+                   static_cast<float>(real_window_size.height) / window_size.height);
+  out_viewport.x *= transform.x;
+  out_viewport.y *= transform.y;
+
+  out_viewport.w *= transform.x;
+  out_viewport.h *= transform.y;
+
+  out_scale.x = scale * transform.x;
+  out_scale.y = scale * transform.y;
+
+}
+
+inline float
+calculate_scale(const Size& min_size, const Size& max_size,
+                      const Size& window_size,
+                      float magnification)
+{
+  float scale = magnification;
+  if (scale == 0.0f) // magic value
+  {
+    scale = 1.0f;
+
+    // Find the minimum magnification that is needed to fill the screen
+    if (window_size.width > max_size.width ||
+        window_size.height > max_size.height)
+    {
+      scale = std::max(static_cast<float>(window_size.width) / max_size.width,
+                       static_cast<float>(window_size.height) / max_size.height);
+    }
+
+    // If the resulting area would violate min_size, scale it down
+    if (window_size.width / scale < min_size.width ||
+        window_size.height / scale < min_size.height)
+    {
+      scale = std::min(static_cast<float>(window_size.width) / min_size.width,
+                       static_cast<float>(window_size.height) / min_size.height);
+    }
+  }
+
+  return scale;
+}
+
+inline SDL_Rect
+calculate_viewport(const Size& max_size, const Size& window_size, float scale)
+{
+  SDL_Rect viewport;
+
+  viewport.w = std::min(window_size.width,
+                            static_cast<int>(scale * max_size.width));
+  viewport.h = std::min(window_size.height,
+                            static_cast<int>(scale * max_size.height));
+
+  // Center the viewport in the window
+  viewport.x = std::max(0, (window_size.width - viewport.w) / 2);
+  viewport.y = std::max(0, (window_size.height - viewport.h) / 2);
+
+  return viewport;
+}
+
+} // namespace
+
+void calculate_viewport(const Size& min_size, const Size& max_size,
+                        const Size& real_window_size,
+                        float pixel_aspect_ratio, float magnification,
+                        Vector& out_scale,
+                        Size& out_logical_size,
+                        SDL_Rect& out_viewport)
+{
+  // Transform the real window_size by the aspect ratio, then do
+  // calculations on that virtual window_size
+  Size window_size = apply_pixel_aspect_ratio_pre(real_window_size, pixel_aspect_ratio);
+
+  float scale = calculate_scale(min_size, max_size, window_size, magnification);
+
+  // Calculate the new viewport size
+  out_viewport = calculate_viewport(max_size, window_size, scale);
+
+  out_logical_size.width = static_cast<int>(out_viewport.w / scale);
+  out_logical_size.height = static_cast<int>(out_viewport.h / scale);
+
+  // Transform the virtual window_size back into real window coordinates
+  apply_pixel_aspect_ratio_post(real_window_size, window_size, scale,
+                                out_viewport, out_scale);
+}
+
+float calculate_pixel_aspect_ratio(const Size& source, const Size& target)
+{
+  float source_aspect = 16.0f / 9.0f; // random guess
+  if (source != Size(0, 0))
+  {
+    source_aspect =
+      static_cast<float>(source.width) /
+      static_cast<float>(source.height);
+  }
+
+  float target_aspect =
+    static_cast<float>(target.width) /
+    static_cast<float>(target.height);
+
+  return target_aspect / source_aspect;
+}
+
+/* EOF */
diff --git a/src/video/util.hpp b/src/video/util.hpp
new file mode 100644 (file)
index 0000000..87b6784
--- /dev/null
@@ -0,0 +1,36 @@
+//  SuperTux
+//  Copyright (C) 2013 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HEADER_SUPERTUX_VIDEO_UTIL_HPP
+#define HEADER_SUPERTUX_VIDEO_UTIL_HPP
+
+#include "SDL_rect.h"
+
+class Size;
+class Vector;
+
+void calculate_viewport(const Size& min_size, const Size& max_size,
+                        const Size& real_window_size,
+                        float pixel_aspect_ratio, float magnification,
+                        Vector& out_scale,
+                        Size& out_logical_size,
+                        SDL_Rect& out_viewport);
+
+float calculate_pixel_aspect_ratio(const Size& source, const Size& target);
+
+#endif
+
+/* EOF */
index c74e945..e65cad0 100644 (file)
@@ -384,6 +384,7 @@ WorldMap::get_level_target_time(LevelTile& level)
 
     last_position = level.pos;
     last_target_time = level.target_time;
+
   } catch(std::exception& e) {
     log_warning << "Problem when reading level target time: " << e.what() << std::endl;
     return;