.Trashes
ehthumbs.db
Thumbs.db
-.directory
\ No newline at end of file
+.directory
+*~
INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIR})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
-FIND_PACKAGE(SDL REQUIRED)
-INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR})
+INCLUDE(FindPkgConfig)
+PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
+INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS})
+LINK_LIBRARIES(supertux2 ${SDL2_LIBRARIES})
+
+PKG_SEARCH_MODULE(SDL2IMAGE REQUIRED SDL2_image>=2.0.0)
+INCLUDE_DIRECTORIES(${SDL2IMAGE_INCLUDE_DIRS})
+LINK_LIBRARIES(supertux2 ${SDL2IMAGE_LIBRARIES})
SET(HAVE_SDL TRUE)
-FIND_PACKAGE(SDL_image REQUIRED)
-INCLUDE_DIRECTORIES(${SDLIMAGE_INCLUDE_DIR})
+#FIND_PACKAGE(SDL_image REQUIRED)
+#INCLUDE_DIRECTORIES(${SDLIMAGE_INCLUDE_DIR})
OPTION(ENABLE_OPENGL "Enable OpenGL support" ON)
IF(ENABLE_OPENGL)
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)
#include "supertux/menu/keyboard_menu.hpp"
#include "util/gettext.hpp"
#include "util/writer.hpp"
+//#include <SDL_keycode.h> // add by giby
JoystickKeyboardController::JoystickKeyboardController() :
controller(),
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) {
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) {
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;
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);
}
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);
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);
Console::instance->move_cursor(+1);
break;
default:
- int c = event.keysym.unicode;
- if ((c >= 32) && (c <= 126)) {
- Console::instance->input((char)c);
- }
break;
}
}
}
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();
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;
std::cout << std::endl;
}
-SDLKey
+SDL_Keycode
JoystickKeyboardController::reversemap_key(Control c)
{
for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {
#include "control/controller.hpp"
#include <SDL.h>
-
+#include <SDL_keycode.h> // add by giby
#include <map>
#include <string>
#include <vector>
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;
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;
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);
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);
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;
+++ /dev/null
-// 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 */
+++ /dev/null
-// 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 */
+++ /dev/null
-// 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 */
+++ /dev/null
-// 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 */
#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;
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 &&
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 &&
#include "supertux/resources.hpp"
#include "supertux/timer.hpp"
#include "video/font.hpp"
+#include <stdio.h>
static const float FLICK_CURSOR_TIME = 0.5f;
#include "supertux/globals.hpp"
#include "video/drawing_context.hpp"
+#include "video/renderer.hpp"
+#include "video/sdl/sdl_renderer.hpp"
MouseCursor* MouseCursor::current_ = 0;
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);
dictionary_manager(0),
dictionary(0),
token(),
- obst(),
- searchpath()
+ searchpath(),
+ obst()
{
if(translate) {
dictionary_manager = new tinygettext::DictionaryManager();
// 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"
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
//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
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
#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;
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;
#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"
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()
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
// clear input buffer
inputBuffer = "";
inputBufferPosition = 0;
- SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
+ // SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
}
void
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),
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);
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);
// 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;
#include "supertux/globals.hpp"
#include <tinygettext/tinygettext.hpp>
-SDL_Surface* g_screen;
JoystickKeyboardController* g_jk_controller = 0;
tinygettext::DictionaryManager* dictionary_manager = 0;
// global variables
extern JoystickKeyboardController* g_jk_controller;
-extern SDL_Surface* g_screen;
-
extern ScreenManager* g_screen_manager;
extern TextureManager* texture_manager;
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;
#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"
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";
}
}
-#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));
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") {
{
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") {
// 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...
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;
}
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();
// So we simply mount that path here...
std::string dir = FileSystem::dirname(g_config->start_level);
std::string fileProtocol = "file://";
- int position = dir.find(fileProtocol);
+ std::string::size_type position = dir.find(fileProtocol);
if(position != std::string::npos) {
dir = dir.replace(position, fileProtocol.length(), "");
}
}
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();
{}
std::string
-KeyboardMenu::get_key_name(SDLKey key)
+KeyboardMenu::get_key_name(SDL_Keycode key)
{
switch(key) {
case SDLK_UNKNOWN:
case SDLK_LALT:
return _("Left Alt");
default:
- return SDL_GetKeyName((SDLKey) key);
+ return SDL_GetKeyName((SDL_Keycode) key);
}
}
~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() {}
#include <algorithm>
#include <sstream>
+#include <stdio.h>
enum OptionsMenuIDs {
MNID_FULLSCREEN,
}
}
-
- 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)
{
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"))
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;
#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 */
ScreenManager::process_events()
{
g_jk_controller->update();
- Uint8* keystate = SDL_GetKeyState(NULL);
SDL_Event event;
while(SDL_PollEvent(&event))
{
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:
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;
#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(),
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)
// 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;
// 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
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;
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);
};
private:
- Renderer *renderer;
- Lightmap *lightmap;
+ Renderer& renderer;
+ Lightmap& lightmap;
/// the transform stack
std::vector<Transform> transformstack;
}
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;
row++;
}
}
-
+abort:
+
if( surface != NULL ) {
SDL_UnlockSurface(surface);
SDL_FreeSurface(surface);
#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);
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:
static const int LIGHTMAP_DIV = 5;
- SDL_Surface* screen;
boost::shared_ptr<GLTexture> lightmap;
int lightmap_width;
int lightmap_height;
// 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);
// 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)
GLRenderer::~GLRenderer()
{
+ SDL_GL_DeleteContext(glcontext);
+ SDL_DestroyWindow(window);
}
void
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;
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
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;
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?
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;
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();
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();
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 */
#include "video/drawing_request.hpp"
#include "video/renderer.hpp"
+#include "SDL.h"
#include <math.h>
namespace {
{
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[] = {
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:
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 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
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
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");
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_; }
#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
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 */
#include "video/lightmap.hpp"
+#include "SDL.h"
+
class Color;
struct DrawingRequest;
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&);
--- /dev/null
+// 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 */
--- /dev/null
+// 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 */
// 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 */
#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
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&);
#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 : */
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&);
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());
}
--- /dev/null
+// 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 */
--- /dev/null
+// 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 */
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;