SirVer has proposed merging lp:~widelands-dev/widelands/move_drawing_out into lp:widelands with lp:~widelands-dev/widelands/remove_in_memory_image as a prerequisite.
Requested reviews: Widelands Developers (widelands-dev) For more details, see: https://code.launchpad.net/~widelands-dev/widelands/move_drawing_out/+merge/243944 - Moves drawing functions out of Surface into stand alone methods. - Image is now a base class of Surface. This needed some unfortunate multiple inheritance, but I believe that this can be mended with the new font renderer being merged soon. - Removed InMemoryImage. Plain Texture can now be used instead. - Use glReadPixels() for screenshots. This is GL ES 2 compatible and got rid of pixel access to the screen. - Move TextureCache out of graphics and into FontHandler1. The only place that is caching surfaces now is the new text renderer. --- This refactoring fell into place rather easily (except for the multiple inheritance, but that is just two interfaces, so it should not matter). I think I am now in the place where I can look into bunching up blit calls. This is the final optimization that I want to do in the graphics engine for now. -- Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/move_drawing_out into lp:widelands.
=== modified file 'src/editor/CMakeLists.txt' --- src/editor/CMakeLists.txt 2014-11-28 08:33:11 +0000 +++ src/editor/CMakeLists.txt 2014-12-08 05:59:46 +0000 @@ -90,7 +90,6 @@ base_macros base_scoped_timer graphic - graphic_image graphic_surface io_filesystem logic === modified file 'src/editor/ui_menus/editor_tool_change_resources_options_menu.cc' --- src/editor/ui_menus/editor_tool_change_resources_options_menu.cc 2014-11-30 18:49:38 +0000 +++ src/editor/ui_menus/editor_tool_change_resources_options_menu.cc 2014-12-08 05:59:46 +0000 @@ -135,7 +135,7 @@ Widelands::ResourceIndex const nr_resources = world.get_nr_resources(); // Find the maximal width and height for the resource pictures. - uint16_t resource_pic_max_width = 0, resource_pic_max_height = 0; + int resource_pic_max_width = 0, resource_pic_max_height = 0; for (Widelands::ResourceIndex i = 0; i < nr_resources; ++i) { const Image* pic = g_gr->images().get(world.get_resource(i)->get_editor_pic(100000)); resource_pic_max_width = std::max(resource_pic_max_width, pic->width()); === modified file 'src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc' --- src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc 2014-12-08 05:59:45 +0000 +++ src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc 2014-12-08 05:59:46 +0000 @@ -28,7 +28,6 @@ #include "editor/editorinteractive.h" #include "editor/tools/editor_set_terrain_tool.h" #include "graphic/graphic.h" -#include "graphic/in_memory_image.h" #include "graphic/rendertarget.h" #include "graphic/texture.h" #include "logic/map.h" @@ -76,76 +75,82 @@ const Texture& terrain_texture = terrain_descr.get_texture(0); Texture* texture = new Texture(terrain_texture.width(), terrain_texture.height()); - texture->blit(Rect(0, 0, terrain_texture.width(), terrain_texture.height()), - &terrain_texture, + blit(Rect(0, 0, terrain_texture.width(), terrain_texture.height()), + terrain_texture, Rect(0, 0, terrain_texture.width(), terrain_texture.height()), 1., - BlendMode::UseAlpha); + BlendMode::UseAlpha, texture); Point pt(1, terrain_texture.height() - kSmallPicHeight - 1); if (ter_is == TerrainDescription::GREEN) { - texture->blit(Rect(pt.x, pt.y, green->width(), green->height()), - green->texture(), - Rect(0, 0, green->width(), green->height()), - 1., - BlendMode::UseAlpha); + blit(Rect(pt.x, pt.y, green->width(), green->height()), + *green, + Rect(0, 0, green->width(), green->height()), + 1., + BlendMode::UseAlpha, + texture); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("arable")); } else { if (ter_is & TerrainDescription::WATER) { - texture->blit(Rect(pt.x, pt.y, water->width(), water->height()), - water->texture(), - Rect(0, 0, water->width(), water->height()), - 1., - BlendMode::UseAlpha); + blit(Rect(pt.x, pt.y, water->width(), water->height()), + *water, + Rect(0, 0, water->width(), water->height()), + 1., + BlendMode::UseAlpha, + texture); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("aquatic")); } else if (ter_is & TerrainDescription::MOUNTAIN) { - texture->blit(Rect(pt.x, pt.y, mountain->width(), mountain->height()), - mountain->texture(), - Rect(0, 0, mountain->width(), mountain->height()), - 1., - BlendMode::UseAlpha); + blit(Rect(pt.x, pt.y, mountain->width(), mountain->height()), + *mountain, + Rect(0, 0, mountain->width(), mountain->height()), + 1., + BlendMode::UseAlpha, + texture); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("mountainous")); } if (ter_is & TerrainDescription::ACID) { - texture->blit(Rect(pt.x, pt.y, dead->width(), dead->height()), - dead->texture(), - Rect(0, 0, dead->width(), dead->height()), - 1., - BlendMode::UseAlpha); + blit(Rect(pt.x, pt.y, dead->width(), dead->height()), + *dead, + Rect(0, 0, dead->width(), dead->height()), + 1., + BlendMode::UseAlpha, + texture); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("dead")); } if (ter_is & TerrainDescription::UNPASSABLE) { - texture->blit(Rect(pt.x, pt.y, unpassable->width(), unpassable->height()), - unpassable->texture(), - Rect(0, 0, unpassable->width(), unpassable->height()), - 1., - BlendMode::UseAlpha); + blit(Rect(pt.x, pt.y, unpassable->width(), unpassable->height()), + *unpassable, + Rect(0, 0, unpassable->width(), unpassable->height()), + 1., + BlendMode::UseAlpha, + texture); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("unpassable")); } if (ter_is & TerrainDescription::DRY) { - texture->blit(Rect(pt.x, pt.y, dry->width(), dry->height()), - dry->texture(), - Rect(0, 0, dry->width(), dry->height()), - 1., - BlendMode::UseAlpha); + blit(Rect(pt.x, pt.y, dry->width(), dry->height()), + *dry, + Rect(0, 0, dry->width(), dry->height()), + 1., + BlendMode::UseAlpha, + texture); /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("treeless")); } } // Make sure we delete this later on. - offscreen_images->emplace_back(new_in_memory_image(texture)); + offscreen_images->emplace_back(texture); break; } /** TRANSLATORS: %1% = terrain name, %2% = list of terrain types */ === modified file 'src/game_io/game_preload_packet.cc' --- src/game_io/game_preload_packet.cc 2014-11-23 11:56:13 +0000 +++ src/game_io/game_preload_packet.cc 2014-12-08 05:59:46 +0000 @@ -26,7 +26,6 @@ #include "base/time_string.h" #include "graphic/graphic.h" -#include "graphic/in_memory_image.h" #include "graphic/minimap_renderer.h" #include "logic/game.h" #include "logic/game_data_error.h" === modified file 'src/graphic/CMakeLists.txt' --- src/graphic/CMakeLists.txt 2014-12-08 05:59:45 +0000 +++ src/graphic/CMakeLists.txt 2014-12-08 05:59:46 +0000 @@ -25,9 +25,8 @@ io_stream ) -wl_library(graphic_image +wl_library(graphic_image_cache SRCS - image.h image_cache.cc image_cache.h USES_SDL2 @@ -69,6 +68,7 @@ gl/draw_rect_program.h gl/fill_rect_program.cc gl/fill_rect_program.h + image.h screen.cc screen.h surface.cc @@ -135,7 +135,6 @@ base_macros economy graphic - graphic_image graphic_surface logic wui_mapview_pixelfunctions @@ -157,8 +156,6 @@ font_handler1.h graphic.cc graphic.h - in_memory_image.cc - in_memory_image.h rendertarget.cc rendertarget.h richtext.cc @@ -179,7 +176,7 @@ build_info graphic_color graphic_gl_utils - graphic_image + graphic_image_cache graphic_image_io graphic_surface graphic_text === modified file 'src/graphic/animation.cc' --- src/graphic/animation.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/animation.cc 2014-12-08 05:59:46 +0000 @@ -39,7 +39,6 @@ #include "graphic/image.h" #include "graphic/image_cache.h" #include "graphic/surface.h" -#include "graphic/texture_cache.h" #include "io/filesystem/layered_filesystem.h" #include "logic/bob.h" #include "logic/instances.h" @@ -326,17 +325,19 @@ assert(idx < nr_frames()); if (!hasplrclrs_ || clr == nullptr) { - target->blit(Rect(dst.x, dst.y, srcrc.w, srcrc.h), - frames_.at(idx)->texture(), + ::blit(Rect(dst.x, dst.y, srcrc.w, srcrc.h), + *frames_.at(idx), + srcrc, + 1., + BlendMode::UseAlpha, + target); + } else { + blit_blended(Rect(dst.x, dst.y, srcrc.w, srcrc.h), + *frames_.at(idx), + *pcmasks_.at(idx), srcrc, - 1., - BlendMode::UseAlpha); - } else { - target->blit_blended(Rect(dst.x, dst.y, srcrc.w, srcrc.h), - frames_.at(idx)->texture(), - pcmasks_.at(idx)->texture(), - srcrc, - *clr); + *clr, + target); } } === modified file 'src/graphic/font_handler.cc' --- src/graphic/font_handler.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/font_handler.cc 2014-12-08 05:59:46 +0000 @@ -30,7 +30,6 @@ #include "base/log.h" #include "base/wexception.h" #include "graphic/graphic.h" -#include "graphic/in_memory_image.h" #include "graphic/rendertarget.h" #include "graphic/texture.h" #include "graphic/wordwrap.h" @@ -196,7 +195,7 @@ return; } - lce.image = new_in_memory_image(new Texture(text_surface)); + lce.image.reset(new Texture(text_surface)); lce.width = lce.image->width(); lce.height = lce.image->height(); } === modified file 'src/graphic/font_handler1.cc' --- src/graphic/font_handler1.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/font_handler1.cc 2014-12-08 05:59:46 +0000 @@ -24,6 +24,7 @@ #include <boost/lexical_cast.hpp> #include <boost/utility.hpp> +#include "base/log.h" #include "base/wexception.h" #include "graphic/graphic.h" #include "graphic/image.h" @@ -42,22 +43,41 @@ namespace { +/// The size of the richtext surface cache in bytes. All work that the richtext +//renderer does is / cached in this cache until it overflows. +const uint32_t RICHTEXT_SURFACE_CACHE = 160 << 20; // shifting converts to MB + // An Image implementation that recreates a rich text texture when needed on // the fly. It is meant to be saved into the ImageCache. class RTImage : public Image { public: - RTImage - (const string& ghash, TextureCache* texture_cache, RT::Renderer* - rt_renderer, const string& text, uint16_t gwidth) - : hash_(ghash), text_(text), width_(gwidth), texture_cache_(texture_cache), - rt_renderer_(rt_renderer) - {} + RTImage(const string& ghash, + TextureCache* texture_cache, + RT::Renderer* rt_renderer, + const string& text, + int gwidth) + : hash_(ghash), + text_(text), + width_(gwidth), + texture_cache_(texture_cache), + rt_renderer_(rt_renderer) { + } virtual ~RTImage() {} // Implements Image. - uint16_t width() const override {return texture()->width();} - uint16_t height() const override {return texture()->height();} - Texture* texture() const override { + int width() const override {return texture()->width();} + int height() const override {return texture()->height();} + + int get_gl_texture() const override { + return texture()->get_gl_texture(); + } + + const FloatRect& texture_coordinates() const override { + return texture()->texture_coordinates(); + } + +private: + Texture* texture() const { Texture* surf = texture_cache_->get(hash_); if (surf) return surf; @@ -67,10 +87,9 @@ return surf; } -private: const string hash_; const string text_; - uint16_t width_; + int width_; // Nothing owned. TextureCache* const texture_cache_; @@ -86,8 +105,11 @@ // be a problem. class FontHandler1 : public IFontHandler1 { public: - FontHandler1(ImageCache* image_cache, TextureCache* texture_cache, RT::Renderer* renderer) : - texture_cache_(texture_cache), image_cache_(image_cache), renderer_(renderer) {} + FontHandler1(ImageCache* image_cache) + : texture_cache_(create_texture_cache(RICHTEXT_SURFACE_CACHE)), + renderer_(new RT::Renderer(image_cache, texture_cache_.get())), + image_cache_(image_cache) { + } virtual ~FontHandler1() {} const Image* render(const string& text, uint16_t w = 0) override { @@ -96,21 +118,21 @@ if (image_cache_->has(hash)) return image_cache_->get(hash); - std::unique_ptr<RTImage> image(new RTImage(hash, texture_cache_, renderer_.get(), text, w)); - image->texture(); // force the rich text to get rendered in case there is an exception thrown. + std::unique_ptr<RTImage> image( + new RTImage(hash, texture_cache_.get(), renderer_.get(), text, w)); + image->width(); // force the rich text to get rendered in case there is an exception thrown. return image_cache_->insert(hash, std::move(image)); } private: - TextureCache* const texture_cache_; // not owned + std::unique_ptr<TextureCache> texture_cache_; + std::unique_ptr<RT::Renderer> renderer_; ImageCache* const image_cache_; // not owned - std::unique_ptr<RT::Renderer> renderer_; }; IFontHandler1 * create_fonthandler(Graphic* gr) { - return new FontHandler1( - &gr->images(), &gr->textures(), new RT::Renderer(&gr->images(), &gr->textures())); + return new FontHandler1(&gr->images()); } IFontHandler1 * g_fh1 = nullptr; === modified file 'src/graphic/graphic.cc' --- src/graphic/graphic.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/graphic.cc 2014-12-08 05:59:46 +0000 @@ -19,6 +19,8 @@ #include "graphic/graphic.h" +#include <memory> + #include "base/log.h" #include "base/wexception.h" #include "build_info.h" @@ -30,7 +32,6 @@ #include "graphic/rendertarget.h" #include "graphic/screen.h" #include "graphic/texture.h" -#include "graphic/texture_cache.h" #include "io/filesystem/layered_filesystem.h" #include "io/streamwrite.h" #include "notifications/notifications.h" @@ -41,10 +42,6 @@ namespace { -/// The size of the transient (i.e. temporary) surfaces in the cache in bytes. -/// These are all surfaces that are not loaded from disk. -const uint32_t TRANSIENT_TEXTURE_CACHE_SIZE = 160 << 20; // shifting converts to MB - // Sets the icon for the application. void set_icon(SDL_Window* sdl_window) { #ifndef _WIN32 @@ -66,7 +63,6 @@ : m_window_mode_width(window_mode_w), m_window_mode_height(window_mode_h), m_update(true), - texture_cache_(create_texture_cache(TRANSIENT_TEXTURE_CACHE_SIZE)), image_cache_(new ImageCache()), animation_manager_(new AnimationManager()) { @@ -144,7 +140,6 @@ Graphic::~Graphic() { - texture_cache_->flush(); // TODO(unknown): this should really not be needed, but currently is :( if (UI::g_fh) UI::g_fh->flush(); @@ -280,8 +275,8 @@ * @param surf The Surface to save * @param sw a StreamWrite where the png is written to */ -void Graphic::save_png(const Image* image, StreamWrite * sw) const { - save_surface_to_png(image->texture(), sw, COLOR_TYPE::RGBA); +void Graphic::save_png(Texture* texture, StreamWrite * sw) const { + save_to_png(texture, sw, ColorType::RGBA); } /** @@ -290,7 +285,6 @@ void Graphic::screenshot(const string& fname) const { log("Save screenshot to %s\n", fname.c_str()); - StreamWrite * sw = g_fs->open_stream_write(fname); - save_surface_to_png(screen_.get(), sw, COLOR_TYPE::RGB); - delete sw; + std::unique_ptr<StreamWrite> sw(g_fs->open_stream_write(fname)); + save_to_png(screen_->to_texture().get(), sw.get(), ColorType::RGB); } === modified file 'src/graphic/graphic.h' --- src/graphic/graphic.h 2014-11-27 21:29:21 +0000 +++ src/graphic/graphic.h 2014-12-08 05:59:46 +0000 @@ -28,12 +28,9 @@ #include "notifications/notifications.h" #include "notifications/note_ids.h" -#define MAX_RECTS 20 - class AnimationManager; class RenderTarget; -class Surface; -class TextureCache; +class Screen; class StreamWrite; // Will be send whenever the resolution changes. @@ -73,11 +70,10 @@ void refresh(); SDL_Window* get_sdlwindow() {return m_sdl_window;} - TextureCache& textures() const {return *texture_cache_.get();} ImageCache& images() const {return *image_cache_.get();} AnimationManager& animations() const {return *animation_manager_.get();} - void save_png(const Image*, StreamWrite*) const; + void save_png(Texture*, StreamWrite*) const; void screenshot(const std::string& fname) const; @@ -91,7 +87,7 @@ /// This is the main screen Surface. /// A RenderTarget for this can be retrieved with get_render_target() - std::unique_ptr<Surface> screen_; + std::unique_ptr<Screen> screen_; /// This saves a copy of the screen SDL_Surface. This is needed for /// opengl rendering as the SurfaceOpenGL does not use it. It allows /// manipulation the screen context. @@ -102,11 +98,9 @@ /// This marks the complete screen for updating. bool m_update; - /// Volatile cache of Hardware dependant textures. - std::unique_ptr<TextureCache> texture_cache_; - /// Non-volatile cache of hardware independent images. The use the - /// texture_cache_ to cache their pixel data. + /// Non-volatile cache of independent images. std::unique_ptr<ImageCache> image_cache_; + /// This holds all animations. std::unique_ptr<AnimationManager> animation_manager_; }; === modified file 'src/graphic/image.h' --- src/graphic/image.h 2014-12-08 05:59:45 +0000 +++ src/graphic/image.h 2014-12-08 05:59:46 +0000 @@ -25,6 +25,7 @@ #include <stdint.h> #include "base/macros.h" +#include "base/rect.h" class Texture; @@ -37,9 +38,15 @@ Image() = default; virtual ~Image() {} - virtual uint16_t width() const = 0; - virtual uint16_t height() const = 0; - virtual Texture* texture() const = 0; + // Dimensions of this Image in pixels. + virtual int width() const = 0; + virtual int height() const = 0; + + // OpenGL texture and texture coordinates backing this Image. This can + // change at any time, so do not hold one to this value for more than one + // frame. + virtual int get_gl_texture() const = 0; + virtual const FloatRect& texture_coordinates() const = 0; private: DISALLOW_COPY_AND_ASSIGN(Image); === modified file 'src/graphic/image_cache.cc' --- src/graphic/image_cache.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/image_cache.cc 2014-12-08 05:59:46 +0000 @@ -26,7 +26,6 @@ #include "base/log.h" #include "graphic/image.h" #include "graphic/image_io.h" -#include "graphic/in_memory_image.h" #include "graphic/texture.h" ImageCache::ImageCache() { @@ -49,7 +48,7 @@ const Image* ImageCache::get(const std::string& hash) { ImageMap::const_iterator it = images_.find(hash); if (it == images_.end()) { - images_.insert(make_pair(hash, new_in_memory_image(load_image(hash).release()))); + images_.insert(make_pair(hash, load_image(hash))); return get(hash); } return it->second.get(); === modified file 'src/graphic/image_io.cc' --- src/graphic/image_io.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/image_io.cc 2014-12-08 05:59:46 +0000 @@ -33,13 +33,13 @@ namespace { -// A helper function for save_surface_to_png. Writes the compressed data to +// A helper function for save_to_png. Writes the compressed data to // the StreamWrite. void png_write_function(png_structp png_ptr, png_bytep png_data, png_size_t length) { static_cast<StreamWrite*>(png_get_io_ptr(png_ptr))->data(png_data, length); } -// A helper function for save_surface_to_png. +// A helper function for save_to_png. // Flush function to avoid crashes with default libpng flush function void png_flush_function(png_structp png_ptr) { static_cast<StreamWrite*>(png_get_io_ptr(png_ptr))->flush(); @@ -82,23 +82,23 @@ return sdlsurf; } -bool save_surface_to_png(Surface* surface, StreamWrite* sw, COLOR_TYPE color_type) { +bool save_to_png(Texture* texture, StreamWrite* sw, ColorType color_type) { png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, static_cast<png_voidp>(nullptr), nullptr, nullptr); if (!png_ptr) - throw wexception("save_surface_to_png: could not create png struct"); + throw wexception("save_to_png: could not create png struct"); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, static_cast<png_infopp>(nullptr)); - throw wexception("save_surface_to_png: could not create png info struct"); + throw wexception("save_to_png: could not create png info struct"); } // Set jump for error if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); - throw wexception("save_surface_to_png: Error writing PNG!"); + throw wexception("save_to_png: Error writing PNG!"); } // Set another write function. This is potentially dangerouse because the @@ -112,10 +112,10 @@ // Fill info struct png_set_IHDR(png_ptr, info_ptr, - surface->width(), - surface->height(), + texture->width(), + texture->height(), 8, - (color_type == COLOR_TYPE::RGB) ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, + (color_type == ColorType::RGB) ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); @@ -123,22 +123,22 @@ // Start writing png_write_info(png_ptr, info_ptr); { - const uint16_t surf_w = surface->width(); - const uint16_t surf_h = surface->height(); - const uint32_t row_size = (color_type == COLOR_TYPE::RGB) ? 3 * surf_w : 4 * surf_w; + const uint16_t surf_w = texture->width(); + const uint16_t surf_h = texture->height(); + const uint32_t row_size = (color_type == ColorType::RGB) ? 3 * surf_w : 4 * surf_w; std::unique_ptr<png_byte[]> row(new png_byte[row_size]); // Write each row - const SDL_PixelFormat& fmt = surface->format(); - surface->lock(Surface::Lock_Normal); + const SDL_PixelFormat& fmt = texture->format(); + texture->lock(); // Write each row RGBAColor color; - if (color_type == COLOR_TYPE::RGB) { + if (color_type == ColorType::RGB) { for (uint32_t y = 0; y < surf_h; ++y) { for (uint32_t x = 0; x < surf_w; ++x) { - color.set(fmt, surface->get_pixel(x, y)); + color.set(fmt, texture->get_pixel(x, y)); row[3 * x] = color.r; row[3 * x + 1] = color.g; row[3 * x + 2] = color.b; @@ -148,7 +148,7 @@ } else { for (uint32_t y = 0; y < surf_h; ++y) { for (uint32_t x = 0; x < surf_w; ++x) { - color.set(fmt, surface->get_pixel(x, y)); + color.set(fmt, texture->get_pixel(x, y)); row[4 * x] = color.r; row[4 * x + 1] = color.g; row[4 * x + 2] = color.b; @@ -157,7 +157,7 @@ png_write_row(png_ptr, row.get()); } } - surface->unlock(Surface::Unlock_NoChange); + texture->unlock(Texture::Unlock_NoChange); } // End write png_write_end(png_ptr, info_ptr); === modified file 'src/graphic/image_io.h' --- src/graphic/image_io.h 2014-12-08 05:59:45 +0000 +++ src/graphic/image_io.h 2014-12-08 05:59:46 +0000 @@ -28,9 +28,7 @@ class FileSystem; class Texture; class StreamWrite; -class Surface; struct SDL_Surface; -enum class COLOR_TYPE {RGB, RGBA}; class ImageNotFound : public WException { public: @@ -51,7 +49,8 @@ /// Loads the image 'fn' from 'fs' into an SDL_Surface. Caller must SDL_FreeSurface() the returned value. SDL_Surface* load_image_as_sdl_surface(const std::string& fn, FileSystem* fs = nullptr); -/// Saves the 'surface' to 'sw' as a PNG. -bool save_surface_to_png(Surface* surface, StreamWrite* sw, COLOR_TYPE color_type); +/// Saves the 'texture' to 'sw' as a PNG. +enum class ColorType {RGB, RGBA}; +bool save_to_png(Texture* texture, StreamWrite* sw, ColorType color_type); #endif // end of include guard: WL_GRAPHIC_IMAGE_IO_H === renamed file 'src/graphic/in_memory_image.cc' => 'src/graphic/in_memory_image.cc.THIS' --- src/graphic/in_memory_image.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/in_memory_image.cc.THIS 2014-12-08 05:59:46 +0000 @@ -38,25 +38,24 @@ // or prepare for core dumps. class InMemoryImage : public Image { public: -<<<<<<< TREE InMemoryImage(const string& ghash, Texture* init_texture) : hash_(ghash), texture_(init_texture) {} -======= - InMemoryImage(Texture* texture) : - texture_(texture) {} ->>>>>>> MERGE-SOURCE virtual ~InMemoryImage() { } // Implements Image. uint16_t width() const override {return texture_->width();} uint16_t height() const override {return texture_->height();} + // Note: hash will mostly be dummy values for this implementation. It should + // not wind up in ImageCache, otherwise the ownership question is not clear. + const string& hash() const override {return hash_;} Texture* texture() const override {return texture_.get();} private: + const string hash_; std::unique_ptr<Texture> texture_; }; -std::unique_ptr<const Image> new_in_memory_image(Texture* texture) { - return std::unique_ptr<const Image>(new InMemoryImage(texture)); +const Image* new_in_memory_image(const string& hash, Texture* texture) { + return new InMemoryImage(hash, texture); } === removed file 'src/graphic/in_memory_image.h' --- src/graphic/in_memory_image.h 2014-12-08 05:59:45 +0000 +++ src/graphic/in_memory_image.h 1970-01-01 00:00:00 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2006-2013 by the Widelands Development Team - * - * 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 2 - * 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef WL_GRAPHIC_IN_MEMORY_IMAGE_H -#define WL_GRAPHIC_IN_MEMORY_IMAGE_H - -#include <memory> - -class Texture; -class Image; - -std::unique_ptr<const Image> new_in_memory_image(Texture* texture); - -#endif // end of include guard: WL_GRAPHIC_IN_MEMORY_IMAGE_H === modified file 'src/graphic/minimap_renderer.cc' --- src/graphic/minimap_renderer.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/minimap_renderer.cc 2014-12-08 05:59:46 +0000 @@ -25,8 +25,6 @@ #include "economy/flag.h" #include "economy/road.h" #include "graphic/graphic.h" -#include "graphic/image.h" -#include "graphic/in_memory_image.h" #include "graphic/texture.h" #include "logic/field.h" #include "logic/map.h" @@ -260,7 +258,6 @@ const Player* player, const Point& viewpoint, MiniMapLayer layers) { - // First create a temporary SDL Surface to draw the minimap. // TODO(unknown): Currently the minimap is redrawn every frame. That is not really // necesary. The created texture could be cached and only redrawn two // or three times per second @@ -271,12 +268,12 @@ Texture* texture = new Texture(map_w, map_h); assert(texture->format().BytesPerPixel == sizeof(uint32_t)); - texture->fill_rect(Rect(0, 0, texture->width(), texture->height()), RGBAColor(0, 0, 0, 255)); - texture->lock(Surface::Lock_Normal); + fill_rect(Rect(0, 0, texture->width(), texture->height()), RGBAColor(0, 0, 0, 255), texture); + texture->lock(); draw_minimap_int(texture, egbase, player, viewpoint, layers); - texture->unlock(Surface::Unlock_Update); + texture->unlock(Texture::Unlock_Update); return std::unique_ptr<Texture>(texture); } @@ -308,7 +305,5 @@ // Render minimap std::unique_ptr<Texture> texture(draw_minimap(egbase, player, viewpoint, layers)); - std::unique_ptr<const Image> image(new_in_memory_image(texture.release())); - g_gr->save_png(image.get(), streamwrite); - image.reset(); + g_gr->save_png(texture.get(), streamwrite); } === modified file 'src/graphic/minimap_renderer.h' --- src/graphic/minimap_renderer.h 2014-11-26 09:36:46 +0000 +++ src/graphic/minimap_renderer.h 2014-12-08 05:59:46 +0000 @@ -56,7 +56,7 @@ /// Render the minimap. If player is not nullptr, it renders from that player's /// point of view. -/// \param viewpoint: top left corner in map coordinates +/// \param viewpoint top left corner in map coordinates std::unique_ptr<Texture> draw_minimap (const Widelands::EditorGameBase& egbase, const Widelands::Player* player, const Point& viewpoint, MiniMapLayer layers); === modified file 'src/graphic/rendertarget.cc' --- src/graphic/rendertarget.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/rendertarget.cc 2014-12-08 05:59:46 +0000 @@ -127,10 +127,13 @@ (int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor& color, uint8_t gwidth) { - m_surface->draw_line - (x1 + m_offset.x + m_rect.x, y1 + m_offset.y + m_rect.y, - x2 + m_offset.x + m_rect.x, y2 + m_offset.y + m_rect.y, color, - gwidth); + ::draw_line(x1 + m_offset.x + m_rect.x, + y1 + m_offset.y + m_rect.y, + x2 + m_offset.x + m_rect.x, + y2 + m_offset.y + m_rect.y, + color, + gwidth, + m_surface); } /** @@ -139,22 +142,23 @@ void RenderTarget::draw_rect(const Rect& rect, const RGBColor& clr) { Rect r(rect); - if (clip(r)) - m_surface->draw_rect(r, clr); + if (clip(r)) { + ::draw_rect(r, clr, m_surface); + } } void RenderTarget::fill_rect(const Rect& rect, const RGBAColor& clr) { Rect r(rect); if (clip(r)) - m_surface->fill_rect(r, clr); + ::fill_rect(r, clr, m_surface); } void RenderTarget::brighten_rect(const Rect& rect, int32_t factor) { Rect r(rect); if (clip(r)) - m_surface->brighten_rect(r, factor); + ::brighten_rect(r, factor, m_surface); } /** @@ -171,11 +175,12 @@ Rect srcrc(Point(0, 0), image->width(), image->height()); if (to_surface_geometry(&destination_point, &srcrc)) { - m_surface->blit(Rect(destination_point.x, destination_point.y, srcrc.w, srcrc.h), - image->texture(), - srcrc, - 1., - blend_mode); + ::blit(Rect(destination_point.x, destination_point.y, srcrc.w, srcrc.h), + *image, + srcrc, + 1., + blend_mode, + m_surface); } } @@ -197,11 +202,12 @@ Point destination_point(dst); if (to_surface_geometry(&destination_point, &srcrc)) - m_surface->blit(Rect(destination_point.x, destination_point.y, srcrc.w, srcrc.h), - image->texture(), - srcrc, - 1., - blend_mode); + ::blit(Rect(destination_point.x, destination_point.y, srcrc.w, srcrc.h), + *image, + srcrc, + 1., + blend_mode, + m_surface); } void RenderTarget::blitrect_scale(const Rect& dst, @@ -213,11 +219,12 @@ Point destination_point(dst.x, dst.y); Rect srcrect(source_rect); if (to_surface_geometry(&destination_point, &srcrect)) { - m_surface->blit(Rect(destination_point.x, destination_point.y, dst.w, dst.h), - image->texture(), - source_rect, - opacity, - blend_mode); + ::blit(Rect(destination_point.x, destination_point.y, dst.w, dst.h), + *image, + source_rect, + opacity, + blend_mode, + m_surface); } } @@ -228,11 +235,12 @@ Point destination_point(destination_rect.x, destination_rect.y); Rect srcrect(source_rect); if (to_surface_geometry(&destination_point, &srcrect)) { - m_surface->blit_monochrome( + blit_monochrome( Rect(destination_point.x, destination_point.y, destination_rect.w, destination_rect.h), - image->texture(), + *image, source_rect, - blend); + blend, + m_surface); } } @@ -289,7 +297,7 @@ srcrc.w = r.w - tx; const Rect dst_rect(r.x + tx, r.y + ty, srcrc.w, srcrc.h); - m_surface->blit(dst_rect, image->texture(), srcrc, 1., blend_mode); + ::blit(dst_rect, *image, srcrc, 1., blend_mode, m_surface); tx += srcrc.w; === modified file 'src/graphic/screen.cc' --- src/graphic/screen.cc 2014-11-24 06:31:16 +0000 +++ src/graphic/screen.cc 2014-12-08 05:59:46 +0000 @@ -20,13 +20,13 @@ #include <algorithm> #include <cassert> +#include <memory> +#include "base/wexception.h" #include "graphic/gl/utils.h" +#include "graphic/texture.h" -Screen::Screen(uint16_t w, uint16_t h) -{ - m_w = w; - m_h = h; +Screen::Screen(int w, int h) : m_w(w), m_h(h) { } void Screen::pixel_to_gl(float* x, float* y) const { @@ -34,50 +34,46 @@ *y = 1. - (*y / m_h) * 2.; } -/** - * Swap order of rows in m_pixels, to compensate for the upside-down nature of the - * OpenGL coordinate system. - */ -void Screen::swap_rows() -{ - uint8_t * begin_row = m_pixels.get(); - uint8_t * end_row = m_pixels.get() + (m_w * (m_h - 1) * 4); - +void Screen::setup_gl() { + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +int Screen::width() const { + return m_w; +} + +int Screen::height() const { + return m_h; +} + +std::unique_ptr<Texture> Screen::to_texture() const { + std::unique_ptr<uint8_t[]> pixels(new uint8_t[m_w * m_h * 4]); + glReadPixels(0, 0, m_w, m_h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); + + // Swap order of rows in m_pixels, to compensate for the upside-down nature of the + // OpenGL coordinate system. + uint8_t* begin_row = pixels.get(); + uint8_t* end_row = pixels.get() + (m_w * (m_h - 1) * 4); while (begin_row < end_row) { - for (uint16_t x = 0; x < m_w * 4; ++x) + for (int x = 0; x < m_w * 4; ++x) { std::swap(begin_row[x], end_row[x]); - + } begin_row += m_w * 4; end_row -= m_w * 4; } -} - -void Screen::lock(Surface::LockMode mode) -{ - assert(!m_pixels); - - m_pixels.reset(new uint8_t[m_w * m_h * 4]); - - if (mode == Lock_Normal) { - // TODO(unknown): terrain dither picture somehow leave the alpha - // channel with non-1 values, so it is cleared before - // accessing pixels. - glColorMask(false, false, false, true); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glColorMask(true, true, true, true); - glReadPixels(0, 0, m_w, m_h, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels.get()); - swap_rows(); - } -} - -void Screen::unlock(Surface::UnlockMode mode) -{ - assert(m_pixels); - - if (mode == Unlock_Update) { - swap_rows(); - glDrawPixels(m_w, m_h, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels.get()); - } - - m_pixels.reset(nullptr); + + // Ownership of pixels is not taken here. But the Texture() transfers it to + // the GPU, frees the SDL surface and after that we are free to free + // 'pixels'. + SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(pixels.get(), + m_w, + m_h, + 32, + m_w * 4, + 0x000000ff, + 0x0000ff00, + 0x00ff0000, + 0xff000000); + + return std::unique_ptr<Texture>(new Texture(surface)); } === modified file 'src/graphic/screen.h' --- src/graphic/screen.h 2014-11-24 06:31:16 +0000 +++ src/graphic/screen.h 2014-12-08 05:59:46 +0000 @@ -19,24 +19,34 @@ #ifndef WL_GRAPHIC_SCREEN_H #define WL_GRAPHIC_SCREEN_H +#include <memory> + +#include "base/macros.h" #include "graphic/surface.h" /** - * This surface represents the screen in OpenGL mode. + * The screen. */ class Screen : public Surface { public: - Screen(uint16_t w, uint16_t h); + Screen(int w, int h); virtual ~Screen() {} - /// Interface implementations - void lock(LockMode) override; - void unlock(UnlockMode) override; + // Implements Surface. + int width() const override; + int height() const override; + void setup_gl() override; + void pixel_to_gl(float* x, float* y) const override; + + // Reads out the current pixels in the framebuffer and returns + // them as a texture for screenshots. This is a very slow process, + // so use with care. + std::unique_ptr<Texture> to_texture() const; private: - void pixel_to_gl(float* x, float* y) const override; + const int m_w, m_h; - void swap_rows(); + DISALLOW_COPY_AND_ASSIGN(Screen); }; #endif // end of include guard: WL_GRAPHIC_SCREEN_H === modified file 'src/graphic/surface.cc' --- src/graphic/surface.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/surface.cc 2014-12-08 05:59:46 +0000 @@ -35,148 +35,58 @@ #include "graphic/texture.h" -uint16_t Surface::width() const { - return m_w; -} - -uint16_t Surface::height() const { - return m_h; -} - -uint8_t * Surface::get_pixels() const -{ - return m_pixels.get(); -} - -uint32_t Surface::get_pixel(uint16_t x, uint16_t y) { - assert(m_pixels); - assert(x < m_w); - assert(y < m_h); - - uint8_t * data = &m_pixels[y * get_pitch() + 4 * x]; - return *(reinterpret_cast<uint32_t *>(data)); -} - -uint16_t Surface::get_pitch() const { - return 4 * m_w; -} - -const SDL_PixelFormat & Surface::format() const { - return Gl::gl_rgba_format(); -} - - -void Surface::set_pixel(uint16_t x, uint16_t y, uint32_t clr) { - assert(m_pixels); - assert(x < m_w); - assert(y < m_h); - - uint8_t * data = &m_pixels[y * get_pitch() + 4 * x]; - *(reinterpret_cast<uint32_t *>(data)) = clr; -} - -FloatRect Surface::to_opengl(const Rect& rect, ConversionMode mode) { +namespace { + +// Convert the 'rect' in pixel space into opengl space. +enum class ConversionMode { + // Convert the rect as given. + kExact, + + // Convert the rect so that the borders are in the center + // of the pixels. + kMidPoint, +}; + +FloatRect to_opengl(const Surface& surface, const Rect& rect, ConversionMode mode) { const float delta = mode == ConversionMode::kExact ? 0. : 0.5; float x1 = rect.x + delta; float y1 = rect.y + delta; - pixel_to_gl(&x1, &y1); + surface.pixel_to_gl(&x1, &y1); float x2 = rect.x + rect.w - delta; float y2 = rect.y + rect.h - delta; - pixel_to_gl(&x2, &y2); - + surface.pixel_to_gl(&x2, &y2); return FloatRect(x1, y1, x2 - x1, y2 - y1); } -void Surface::draw_rect(const Rect& rc, const RGBColor& clr) -{ - glViewport(0, 0, width(), height()); - DrawRectProgram::instance().draw(to_opengl(rc, ConversionMode::kMidPoint), clr); -} - -/** - * Draws a filled rectangle - */ -void Surface::fill_rect(const Rect& rc, const RGBAColor& clr) { - glViewport(0, 0, width(), height()); - - glBlendFunc(GL_ONE, GL_ZERO); - - FillRectProgram::instance().draw(to_opengl(rc, ConversionMode::kExact), clr); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -} - -/** - * Change the brightness of the given rectangle - */ -void Surface::brighten_rect(const Rect& rc, const int32_t factor) -{ - if (!factor) - return; - - glViewport(0, 0, width(), height()); - - // The simple trick here is to fill the rect, but using a different glBlendFunc that will sum - // src and target (or subtract them if factor is negative). - if (factor < 0) { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - } - - glBlendFunc(GL_ONE, GL_ONE); - - const int delta = std::abs(factor); - FillRectProgram::instance().draw( - to_opengl(rc, ConversionMode::kExact), RGBAColor(delta, delta, delta, 0)); - - if (factor < 0) { - glBlendEquation(GL_FUNC_ADD); - } - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -} - -void Surface::draw_line - (int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor& color, uint8_t gwidth) -{ - glViewport(0, 0, width(), height()); - - float gl_x1 = x1 + 0.5; - float gl_y1 = y1 + 0.5; - pixel_to_gl(&gl_x1, &gl_y1); - - float gl_x2 = x2 + 0.5; - float gl_y2 = y2 + 0.5; - pixel_to_gl(&gl_x2, &gl_y2); - - DrawLineProgram::instance().draw(gl_x1, gl_y1, gl_x2, gl_y2, color, gwidth); -} - // Converts the pixel (x, y) in a texture to a gl coordinate in [0, 1]. inline void pixel_to_gl_texture(const int width, const int height, float* x, float* y) { *x = (*x / width); *y = (*y / height); } -void Surface::src_and_dst_rect_to_gl(const Texture* texture, - const Rect& dst_rect, - const Rect& src_rect, - FloatRect* gl_dst_rect, - FloatRect* gl_src_rect) { +// Convert 'dst' and 'srcrc' from pixel space into opengl space, taking into +// account that we might be a subtexture in a bigger texture. +void src_and_dst_rect_to_gl(const Surface& surface, + const Image& image, + const Rect& dst_rect, + const Rect& src_rect, + FloatRect* gl_dst_rect, + FloatRect* gl_src_rect) { // Source Rectangle. We have to take into account that the texture might be // a subtexture in another bigger texture. So we first figure out the pixel // coordinates given it is a full texture (values between 0 and 1) and then // adjust these for the texture coordinates in the parent texture. - const FloatRect& texture_coordinates = texture->texture_coordinates(); + const FloatRect& texture_coordinates = image.texture_coordinates(); float x1 = src_rect.x; float y1 = src_rect.y; - pixel_to_gl_texture(texture->width(), texture->height(), &x1, &y1); + pixel_to_gl_texture(image.width(), image.height(), &x1, &y1); x1 = texture_coordinates.x + x1 * texture_coordinates.w; y1 = texture_coordinates.y + y1 * texture_coordinates.h; float x2 = src_rect.x + src_rect.w; float y2 = src_rect.y + src_rect.h; - pixel_to_gl_texture(texture->width(), texture->height(), &x2, &y2); + pixel_to_gl_texture(image.width(), image.height(), &x2, &y2); x2 = texture_coordinates.x + x2 * texture_coordinates.w; y2 = texture_coordinates.y + y2 * texture_coordinates.h; @@ -185,42 +95,116 @@ gl_src_rect->w = x2 - x1; gl_src_rect->h = y2 - y1; - *gl_dst_rect = to_opengl(dst_rect, ConversionMode::kExact); -} - -void Surface::blit - (const Rect& dst_rect, const Texture* texture, const Rect& src_rect, float opacity, BlendMode blend_mode) -{ - glViewport(0, 0, width(), height()); - - FloatRect gl_dst_rect, gl_src_rect; - src_and_dst_rect_to_gl(texture, dst_rect, src_rect, &gl_dst_rect, &gl_src_rect); - - VanillaBlitProgram::instance().draw( - gl_dst_rect, gl_src_rect, texture->get_gl_texture(), opacity, blend_mode); -} - -void Surface::blit_monochrome(const Rect& dst_rect, - const Texture* texture, - const Rect& src_rect, - const RGBAColor& blend) { - glViewport(0, 0, width(), height()); - - FloatRect gl_dst_rect, gl_src_rect; - src_and_dst_rect_to_gl(texture, dst_rect, src_rect, &gl_dst_rect, &gl_src_rect); + *gl_dst_rect = to_opengl(surface, dst_rect, ConversionMode::kExact); +} + +} // namespace + + +void fill_rect(const Rect& rc, const RGBAColor& clr, Surface* surface) { + surface->setup_gl(); + glViewport(0, 0, surface->width(), surface->height()); + + glBlendFunc(GL_ONE, GL_ZERO); + + FillRectProgram::instance().draw(to_opengl(*surface, rc, ConversionMode::kExact), clr); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +void brighten_rect(const Rect& rc, const int32_t factor, Surface * surface) +{ + if (!factor) + return; + + surface->setup_gl(); + glViewport(0, 0, surface->width(), surface->height()); + + // The simple trick here is to fill the rect, but using a different glBlendFunc that will sum + // src and target (or subtract them if factor is negative). + if (factor < 0) { + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + } + + glBlendFunc(GL_ONE, GL_ONE); + + const int delta = std::abs(factor); + FillRectProgram::instance().draw( + to_opengl(*surface, rc, ConversionMode::kExact), RGBAColor(delta, delta, delta, 0)); + + if (factor < 0) { + glBlendEquation(GL_FUNC_ADD); + } + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +void draw_line + (int x1, int y1, int x2, int y2, const RGBColor& color, int gwidth, Surface * surface) +{ + surface->setup_gl(); + glViewport(0, 0, surface->width(), surface->height()); + + float gl_x1 = x1 + 0.5; + float gl_y1 = y1 + 0.5; + surface->pixel_to_gl(&gl_x1, &gl_y1); + + float gl_x2 = x2 + 0.5; + float gl_y2 = y2 + 0.5; + surface->pixel_to_gl(&gl_x2, &gl_y2); + + DrawLineProgram::instance().draw(gl_x1, gl_y1, gl_x2, gl_y2, color, gwidth); +} + +void blit_monochrome(const Rect& dst_rect, + const Image& image, + const Rect& src_rect, + const RGBAColor& blend, + Surface* surface) { + surface->setup_gl(); + glViewport(0, 0, surface->width(), surface->height()); + + FloatRect gl_dst_rect, gl_src_rect; + src_and_dst_rect_to_gl(*surface, image, dst_rect, src_rect, &gl_dst_rect, &gl_src_rect); MonochromeBlitProgram::instance().draw( - gl_dst_rect, gl_src_rect, texture->get_gl_texture(), blend); + gl_dst_rect, gl_src_rect, image.get_gl_texture(), blend); } -void Surface::blit_blended(const Rect& dst_rect, - const Texture* texture, - const Texture* mask, - const Rect& src_rect, - const RGBColor& blend) { +void blit_blended(const Rect& dst_rect, + const Image& image, + const Image& mask, + const Rect& src_rect, + const RGBColor& blend, + Surface* surface) { + surface->setup_gl(); + glViewport(0, 0, surface->width(), surface->height()); + FloatRect gl_dst_rect, gl_src_rect; - src_and_dst_rect_to_gl(texture, dst_rect, src_rect, &gl_dst_rect, &gl_src_rect); + src_and_dst_rect_to_gl(*surface, image, dst_rect, src_rect, &gl_dst_rect, &gl_src_rect); BlendedBlitProgram::instance().draw( - gl_dst_rect, gl_src_rect, texture->get_gl_texture(), mask->get_gl_texture(), blend); + gl_dst_rect, gl_src_rect, image.get_gl_texture(), mask.get_gl_texture(), blend); +} + +void draw_rect(const Rect& rc, const RGBColor& clr, Surface* surface) { + surface->setup_gl(); + glViewport(0, 0, surface->width(), surface->height()); + DrawRectProgram::instance().draw(to_opengl(*surface, rc, ConversionMode::kMidPoint), clr); +} + +void blit(const Rect& dst_rect, + const Image& image, + const Rect& src_rect, + float opacity, + BlendMode blend_mode, + Surface* surface) { + glViewport(0, 0, surface->width(), surface->height()); + surface->setup_gl(); + + FloatRect gl_dst_rect, gl_src_rect; + src_and_dst_rect_to_gl(*surface, image, dst_rect, src_rect, &gl_dst_rect, &gl_src_rect); + + VanillaBlitProgram::instance().draw( + gl_dst_rect, gl_src_rect, image.get_gl_texture(), opacity, blend_mode); } === modified file 'src/graphic/surface.h' --- src/graphic/surface.h 2014-12-08 05:59:45 +0000 +++ src/graphic/surface.h 2014-12-08 05:59:46 +0000 @@ -26,152 +26,62 @@ #include "base/rect.h" #include "graphic/blend_mode.h" #include "graphic/color.h" +#include "graphic/image.h" class Texture; -/** - * Interface to a basic surfaces that can be used as destination for blitting and drawing. - * It also allows low level pixel access. - */ +// Interface to a basic surfaces that can be used as destination for blitting +// and drawing. It also allows low level pixel access. class Surface { public: Surface() = default; virtual ~Surface() {} /// Dimensions. - uint16_t width() const; - uint16_t height() const; - - /// This draws a part of another surface to this surface - virtual void blit(const Rect& dst, - const Texture*, - const Rect& srcrc, - const float opacity, - BlendMode blend_mode); - - /// This draws a grayed out version. See MonochromeBlitProgram. - virtual void blit_monochrome(const Rect& dst, - const Texture*, - const Rect& srcrc, - const RGBAColor& multiplier); - - /// This draws a playercolor blended image. See BlendedBlitProgram. - virtual void blit_blended(const Rect& dst, - const Texture* image, - const Texture* mask, - const Rect& srcrc, - const RGBColor& blend); - - /// Draws a filled rect to the surface. No blending takes place, the values - // in the target are just replaced (i.e. / BlendMode would be BlendMode::Copy). - virtual void fill_rect(const Rect&, const RGBAColor&); - - /// Draws a rect (frame only) to the surface. - virtual void draw_rect(const Rect&, const RGBColor&); - - /// draw a line to the surface - virtual void draw_line - (int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor& color, uint8_t width = 1); - - /// makes a rectangle on the surface brighter (or darker). - virtual void brighten_rect(const Rect&, int32_t factor); - - /// The functions below are for direct pixel access. This should be used - /// only very sparingly as / it is potentially expensive (especially for - /// OpenGL). At the moment, only the code inside graphic / is actually using - /// this. - enum LockMode { - /** - * Normal mode preserves pre-existing pixel data so that it can - * be read or modified. - */ - Lock_Normal = 0, - - /** - * Discard mode discards pre-existing pixel data. All pixels - * will be undefined unless they are re-written. - */ - Lock_Discard - }; - - enum UnlockMode { - /** - * Update mode will ensure that any changes in the pixel data - * will appear in subsequent operations. - */ - Unlock_Update = 0, - - /** - * NoChange mode indicates that the caller changed no pixel data. - * - * \note If the caller did change pixel data but specifies NoChange - * mode, the results are undefined. - */ - Unlock_NoChange - }; - - /// This returns the pixel format for direct pixel access. - const SDL_PixelFormat & format() const; - - /** - * \return Pitch of the raw pixel data, i.e. the number of bytes - * contained in each image row. This can be strictly larger than - * bytes per pixel times the width. - */ - uint16_t get_pitch() const; - - /** - * \return Pointer to the raw pixel data. - * - * \warning May only be called inside lock/unlock pairs. - */ - uint8_t * get_pixels() const; - - /** - * Lock/Unlock pairs must guard any of the direct pixel access using the - * functions below. - * - * \note Lock/Unlock pairs cannot be nested. - */ - virtual void lock(LockMode) = 0; - virtual void unlock(UnlockMode) = 0; - - uint32_t get_pixel(uint16_t x, uint16_t y); - void set_pixel(uint16_t x, uint16_t y, uint32_t clr); + virtual int width() const = 0; + virtual int height() const = 0; // Converts the given pixel into an OpenGl point. This might // need some flipping of axis, depending if you want to render // on the screen or not. virtual void pixel_to_gl(float* x, float* y) const = 0; -protected: - // Convert the 'rect' in pixel space into opengl space. - enum class ConversionMode { - // Convert the rect as given. - kExact, - - // Convert the rect so that the borders are in the center - // of the pixels. - kMidPoint, - }; - FloatRect to_opengl(const Rect& rect, ConversionMode mode); - - // Convert 'dst' and 'srcrc' from pixel space into opengl space, taking into - // account that we might be a subtexture in a bigger texture. - void src_and_dst_rect_to_gl(const Texture* texture, - const Rect& dst, - const Rect& srcrc, - FloatRect* gl_dst_rect, - FloatRect* gl_src_rect); - - /// Logical width and height of the surface - uint16_t m_w, m_h; - - /// Pixel data, while the texture is locked - std::unique_ptr<uint8_t[]> m_pixels; + // Setups OpenGL to render to this surface. + virtual void setup_gl() = 0; private: DISALLOW_COPY_AND_ASSIGN(Surface); }; +/// Draws a rect (frame only) to the surface. +void draw_rect(const Rect&, const RGBColor&, Surface* destination); + +/// This draws a part of 'texture' to 'surface'. +void blit + (const Rect& dst, const Image&, const Rect& srcrc, const float opacity, + BlendMode blend_mode, Surface* destination); + +/// This draws a grayed out version. See MonochromeBlitProgram. +void +blit_monochrome + (const Rect& dst, const Image&, const Rect& srcrc, + const RGBAColor& multiplier, Surface* destination); + +/// This draws a playercolor blended image. See BlendedBlitProgram. +void blit_blended + (const Rect& dst, const Image& image, const Image& mask, const Rect& + srcrc, const RGBColor& blend, Surface* destination); + +/// Draws a filled rect to the destination. No blending takes place, the values +// in the target are just replaced (i.e. / BlendMode would be BlendMode::Copy). +void fill_rect(const Rect&, const RGBAColor&, Surface* destination); + +/// draw a line to the destination +void draw_line + (int x1, int y1, int x2, int y2, const RGBColor& color, + int width, Surface* destination); + +/// makes a rectangle on the destination brighter (or darker). +void brighten_rect(const Rect&, int factor, Surface* destination); + #endif // end of include guard: WL_GRAPHIC_SURFACE_H === modified file 'src/graphic/text/CMakeLists.txt' --- src/graphic/text/CMakeLists.txt 2014-12-03 19:14:07 +0000 +++ src/graphic/text/CMakeLists.txt 2014-12-08 05:59:46 +0000 @@ -21,7 +21,7 @@ base_exceptions base_geometry graphic_color - graphic_image + graphic_image_cache graphic_image_io graphic_surface io_fileread === modified file 'src/graphic/text/rt_render.cc' --- src/graphic/text/rt_render.cc 2014-12-04 09:00:20 +0000 +++ src/graphic/text/rt_render.cc 2014-12-08 05:59:46 +0000 @@ -333,11 +333,12 @@ Texture* TextNode::render(TextureCache* texture_cache) { const Texture& img = m_font.render(m_txt, m_s.font_color, m_s.font_style, texture_cache); Texture* rv = new Texture(img.width(), img.height()); - rv->blit(Rect(0, 0, img.width(), img.height()), - &img, - Rect(0, 0, img.width(), img.height()), - 1., - BlendMode::Copy); + blit(Rect(0, 0, img.width(), img.height()), + img, + Rect(0, 0, img.width(), img.height()), + 1., + BlendMode::Copy, + rv); return rv; } @@ -365,7 +366,7 @@ Texture* rv = new Texture(m_w, m_h); for (uint16_t curx = 0; curx < m_w; curx += t.width()) { Rect srcrect(Point(0, 0), min<int>(t.width(), m_w - curx), m_h); - rv->blit(Rect(curx, 0, srcrect.w, srcrect.h), &t, srcrect, 1., BlendMode::Copy); + blit(Rect(curx, 0, srcrect.w, srcrect.h), t, srcrect, 1., BlendMode::Copy, rv); } return rv; } @@ -382,7 +383,7 @@ Texture* render(TextureCache* texture_cache) override { if (m_show_spaces) { Texture* rv = new Texture(m_w, m_h); - rv->fill_rect(Rect(0, 0, m_w, m_h), RGBAColor(0xff, 0, 0, 0xff)); + fill_rect(Rect(0, 0, m_w, m_h), RGBAColor(0xff, 0, 0, 0xff), rv); return rv; } return TextNode::render(texture_cache); @@ -434,10 +435,10 @@ dst.y = 0; srcrect.w = dst.w = min<int>(m_bg->width(), m_w - curx); srcrect.h = dst.h = m_h; - rv->blit(dst, m_bg->texture(), srcrect, 1., BlendMode::Copy); + blit(dst, *m_bg, srcrect, 1., BlendMode::Copy, rv); } } else { - rv->fill_rect(Rect(0, 0, m_w, m_h), RGBAColor(255, 255, 255, 0)); + fill_rect(Rect(0, 0, m_w, m_h), RGBAColor(255, 255, 255, 0), rv); } return rv; } @@ -474,13 +475,12 @@ uint16_t hotspot_y() override {return height();} Texture* render(TextureCache* texture_cache) override { Texture* rv = new Texture(width(), height()); - rv->fill_rect(Rect(0, 0, rv->width(), rv->height()), RGBAColor(255, 255, 255, 0)); + fill_rect(Rect(0, 0, rv->width(), rv->height()), RGBAColor(255, 255, 255, 0), rv); // Draw Solid background Color bool set_alpha = true; if (m_bg_clr_set) { - Rect fill_rect(Point(m_margin.left, m_margin.top), m_w, m_h); - rv->fill_rect(fill_rect, m_bg_clr); + fill_rect(Rect(Point(m_margin.left, m_margin.top), m_w, m_h), m_bg_clr, rv); set_alpha = false; } @@ -495,7 +495,7 @@ dst.y = cury; src.w = dst.w = min<int>(m_bg_img->width(), m_w + m_margin.left - curx); src.h = dst.h = min<int>(m_bg_img->height(), m_h + m_margin.top - cury); - rv->blit(dst, m_bg_img->texture(), src, 1., BlendMode::Copy); + blit(dst, *m_bg_img, src, 1., BlendMode::Copy, rv); } } set_alpha = false; @@ -510,7 +510,7 @@ node_texture->height()); Rect src = Rect(0, 0, node_texture->width(), node_texture->height()); - rv->blit(dst, node_texture, src, 1., set_alpha ? BlendMode::Copy : BlendMode::UseAlpha); + blit(dst, *node_texture, src, 1., set_alpha ? BlendMode::Copy : BlendMode::UseAlpha, rv); delete node_texture; } delete n; @@ -561,11 +561,11 @@ Texture* ImgRenderNode::render(TextureCache* /* texture_cache */) { Texture* rv = new Texture(m_image.width(), m_image.height()); - rv->blit(Rect(0, 0, m_image.width(), m_image.height()), - m_image.texture(), + blit(Rect(0, 0, m_image.width(), m_image.height()), + m_image, Rect(0, 0, m_image.width(), m_image.height()), 1., - BlendMode::Copy); + BlendMode::Copy, rv); return rv; } // End: Helper Stuff === modified file 'src/graphic/text/test/CMakeLists.txt' --- src/graphic/text/test/CMakeLists.txt 2014-11-23 10:13:14 +0000 +++ src/graphic/text/test/CMakeLists.txt 2014-12-08 05:59:46 +0000 @@ -21,7 +21,7 @@ render.cc render.h DEPENDS - graphic_image + graphic_image_cache graphic_surface graphic_text io_filesystem === modified file 'src/graphic/text/test/render.cc' --- src/graphic/text/test/render.cc 2014-11-24 07:10:03 +0000 +++ src/graphic/text/test/render.cc 2014-12-08 05:59:46 +0000 @@ -36,7 +36,7 @@ g_fs->add_file_system(&FileSystem::create(RICHTEXT_DATA_DIR)); texture_cache_.reset(create_texture_cache(500 << 20)); // 500 MB - image_cache_.reset(new ImageCache(texture_cache_.get())); + image_cache_.reset(new ImageCache()); renderer_.reset(new RT::Renderer(image_cache_.get(), texture_cache_.get())); } === modified file 'src/graphic/text/test/render_richtext.cc' --- src/graphic/text/test/render_richtext.cc 2014-11-30 13:18:04 +0000 +++ src/graphic/text/test/render_richtext.cc 2014-12-08 05:59:46 +0000 @@ -140,7 +140,7 @@ std::unique_ptr<FileSystem> fs(&FileSystem::create(".")); std::unique_ptr<StreamWrite> sw(fs->open_stream_write(outname)); - if (!save_surface_to_png(texture.get(), sw.get(), COLOR_TYPE::RGBA)) { + if (!save_to_png(texture.get(), sw.get(), ColorType::RGBA)) { std::cout << "Could not encode PNG." << std::endl; } } catch (RT::Exception& e) { === modified file 'src/graphic/texture.cc' --- src/graphic/texture.cc 2014-12-08 05:59:45 +0000 +++ src/graphic/texture.cc 2014-12-08 05:59:46 +0000 @@ -61,14 +61,6 @@ return (fmt.Bmask == 0x000000ff && fmt.Gmask == 0x0000ff00 && fmt.Rmask == 0x00ff0000); } -inline void setup_gl(const GLuint texture) { - glBindFramebuffer(GL_FRAMEBUFFER, GlFramebuffer::instance().id()); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); -} - -inline void reset_gl() { - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} } // namespace @@ -95,9 +87,8 @@ // use freetype directly we might be able to avoid that. uint8_t bpp = surface->format->BytesPerPixel; - if (surface->format->palette || m_w != static_cast<uint32_t>(surface->w) || - m_h != static_cast<uint32_t>(surface->h) || (bpp != 3 && bpp != 4) || - is_bgr_surface(*surface->format)) { + if (surface->format->palette || m_w != surface->w || m_h != surface->h || + (bpp != 3 && bpp != 4) || is_bgr_surface(*surface->format)) { SDL_Surface* converted = empty_sdl_surface(m_w, m_h); assert(converted); SDL_SetSurfaceAlphaMod(converted, SDL_ALPHA_OPAQUE); @@ -146,6 +137,22 @@ } } +int Texture::width() const { + return m_w; +} + +int Texture::height() const { + return m_h; +} + +int Texture::get_gl_texture() const { + return m_texture; +} + +const FloatRect& Texture::texture_coordinates() const { + return m_texture_coordinates; +} + void Texture::pixel_to_gl(float* x, float* y) const { *x = (*x / m_w) * 2. - 1.; *y = (*y / m_h) * 2. - 1.; @@ -175,7 +182,7 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } -void Texture::lock(LockMode mode) { +void Texture::lock() { if (m_w <= 0 || m_h <= 0) { return; } @@ -189,11 +196,9 @@ m_pixels.reset(new uint8_t[m_w * m_h * 4]); - if (mode == Lock_Normal) { - glBindTexture(GL_TEXTURE_2D, m_texture); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels.get()); - glBindTexture(GL_TEXTURE_2D, 0); - } + glBindTexture(GL_TEXTURE_2D, m_texture); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels.get()); + glBindTexture(GL_TEXTURE_2D, 0); } void Texture::unlock(UnlockMode mode) { @@ -213,92 +218,40 @@ m_pixels.reset(nullptr); } -void Texture::draw_rect(const Rect& rectangle, const RGBColor& clr) -{ - if (m_w <= 0 || m_h <= 0) { - return; - } - setup_gl(m_texture); - Surface::draw_rect(rectangle, clr); - reset_gl(); -} - - -/** - * Draws a filled rectangle - */ -void Texture::fill_rect(const Rect& rectangle, const RGBAColor& clr) -{ - if (m_w <= 0 || m_h <= 0) { - return; - } - - setup_gl(m_texture); - Surface::fill_rect(rectangle, clr); - reset_gl(); -} - -/** - * Change the brightness of the given rectangle - */ -void Texture::brighten_rect(const Rect& rectangle, const int32_t factor) -{ - if (m_w <= 0 || m_h <= 0) { - return; - } - - setup_gl(m_texture); - Surface::brighten_rect(rectangle, factor); - reset_gl(); -} - -void Texture::draw_line - (int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor& color, uint8_t gwidth) -{ - if (m_w <= 0 || m_h <= 0) { - return; - } - - setup_gl(m_texture); - Surface::draw_line(x1, y1, x2, y2, color, gwidth); - reset_gl(); -} - -void Texture::blit - (const Rect& dst, const Texture* src, const Rect& srcrc, float opacity, BlendMode blend_mode) -{ - if (m_w <= 0 || m_h <= 0) { - return; - } - - setup_gl(m_texture); - Surface::blit(dst, src, srcrc, opacity, blend_mode); - reset_gl(); -} - -void Texture::blit_monochrome(const Rect& dst, - const Texture* src, - const Rect& srcrc, - const RGBAColor& blend) { - if (m_w <= 0 || m_h <= 0) { - return; - } - - setup_gl(m_texture); - Surface::blit_monochrome(dst, src, srcrc, blend); - reset_gl(); -} - -void Texture::blit_blended(const Rect& dst, - const Texture* image, - const Texture* mask, - const Rect& srcrc, - const RGBColor& blend) { - if (m_w <= 0 || m_h <= 0) { - return; - } - - setup_gl(m_texture); - Surface::blit_blended(dst, image, mask, srcrc, blend); - reset_gl(); +uint8_t * Texture::get_pixels() const +{ + return m_pixels.get(); +} + +uint32_t Texture::get_pixel(uint16_t x, uint16_t y) { + assert(m_pixels); + assert(x < m_w); + assert(y < m_h); + + uint8_t * data = &m_pixels[y * get_pitch() + 4 * x]; + return *(reinterpret_cast<uint32_t *>(data)); +} + +uint16_t Texture::get_pitch() const { + return 4 * m_w; +} + +const SDL_PixelFormat & Texture::format() const { + return Gl::gl_rgba_format(); +} + + +void Texture::set_pixel(uint16_t x, uint16_t y, uint32_t clr) { + assert(m_pixels); + assert(x < m_w); + assert(y < m_h); + + uint8_t * data = &m_pixels[y * get_pitch() + 4 * x]; + *(reinterpret_cast<uint32_t *>(data)) = clr; +} + + +void Texture::setup_gl() { + glBindFramebuffer(GL_FRAMEBUFFER, GlFramebuffer::instance().id()); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); } === modified file 'src/graphic/texture.h' --- src/graphic/texture.h 2014-12-08 05:59:45 +0000 +++ src/graphic/texture.h 2014-12-08 05:59:46 +0000 @@ -19,13 +19,15 @@ #ifndef WL_GRAPHIC_TEXTURE_H #define WL_GRAPHIC_TEXTURE_H +#include <memory> + #include "base/rect.h" #include "graphic/gl/system_headers.h" #include "graphic/surface.h" struct SDL_Surface; -class Texture : public Surface { +class Texture : public Surface, public Image { public: // Create a new surface from an SDL_Surface. If intensity is true, an GL_INTENSITY texture // is created. Ownership is taken. @@ -41,46 +43,59 @@ virtual ~Texture(); - /// Interface implementation - //@{ - void lock(LockMode) override; - void unlock(UnlockMode) override; - - // Note: the following functions are reimplemented here though they - // basically only call the functions in Surface wrapped in calls to - // setup_gl(), reset_gl(). The same functionality can be achieved by making - // those two functions virtual and calling them in Surface. However, - // especially for blit which is called very often and mostly on the screen, - // this costs two virtual function calls which makes a notable difference in - // profiles. - void fill_rect(const Rect&, const RGBAColor&) override; - void draw_rect(const Rect&, const RGBColor&) override; - void brighten_rect(const Rect&, int32_t factor) override; - virtual void draw_line - (int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor&, uint8_t width) override; - void blit(const Rect& dstretc, - const Texture*, - const Rect& srcrc, - float opacity, - BlendMode blend_mode) override; - void - blit_monochrome(const Rect& dst, const Texture*, const Rect& srcrc, const RGBAColor& blend) override; - void blit_blended(const Rect& dst, - const Texture* image, - const Texture* mask, - const Rect& srcrc, - const RGBColor& blend) override; - - GLuint get_gl_texture() const {return m_texture;} - - const FloatRect& texture_coordinates() const { - return m_texture_coordinates; - } + // Implements Surface + int width() const override; + int height() const override; + void setup_gl() override; + void pixel_to_gl(float* x, float* y) const override; + + // Implements Image. + int get_gl_texture() const override; + const FloatRect& texture_coordinates() const override; + + enum UnlockMode { + /** + * Update mode will ensure that any changes in the pixel data + * will appear in subsequent operations. + */ + Unlock_Update = 0, + + /** + * NoChange mode indicates that the caller changed no pixel data. + * + * \note If the caller did change pixel data but specifies NoChange + * mode, the results are undefined. + */ + Unlock_NoChange + }; + + /// This returns the pixel format for direct pixel access. + const SDL_PixelFormat & format() const; + + // Number of bytes per row. + uint16_t get_pitch() const; + + // Pointer to the raw pixel data. May only be called inside lock/unlock + // pairs. + uint8_t * get_pixels() const; + + // Lock/Unlock pairs must guard any of the direct pixel access using the + // functions below. Lock/Unlock pairs cannot be nested. + void lock(); + void unlock(UnlockMode); + + // Returns the color of the pixel as a value as defined by 'format()'. + uint32_t get_pixel(uint16_t x, uint16_t y); + + // Sets the pixel to the 'clr'. + void set_pixel(uint16_t x, uint16_t y, uint32_t clr); private: - void pixel_to_gl(float* x, float* y) const override; void init(uint16_t w, uint16_t h); + // Width and height. + int m_w, m_h; + // True if we own the texture, i.e. if we need to delete it. bool m_owns_texture; @@ -88,6 +103,11 @@ FloatRect m_texture_coordinates; GLuint m_texture; + + /// Pixel data, while the texture is locked + std::unique_ptr<uint8_t[]> m_pixels; + + DISALLOW_COPY_AND_ASSIGN(Texture); }; #endif // end of include guard: WL_GRAPHIC_TEXTURE_H === modified file 'src/graphic/texture_atlas.cc' --- src/graphic/texture_atlas.cc 2014-12-04 21:02:35 +0000 +++ src/graphic/texture_atlas.cc 2014-12-08 05:59:46 +0000 @@ -133,7 +133,7 @@ } std::unique_ptr<Texture> packed_texture(new Texture(root->r.w, root->r.h)); - packed_texture->fill_rect(Rect(0, 0, root->r.w, root->r.h), RGBAColor(0, 0, 0, 0)); + fill_rect(Rect(0, 0, root->r.w, root->r.h), RGBAColor(0, 0, 0, 0), packed_texture.get()); // Sort blocks by index so that they come back in the correct ordering. std::sort(blocks_.begin(), blocks_.end(), [](const Block& i, const Block& j) { @@ -141,12 +141,12 @@ }); for (Block& block : blocks_) { - packed_texture->blit( - Rect(block.node->r.x, block.node->r.y, block.texture->width(), block.texture->height()), - block.texture, - Rect(0, 0, block.texture->width(), block.texture->height()), - 1., - BlendMode::UseAlpha); + blit(Rect(block.node->r.x, block.node->r.y, block.texture->width(), block.texture->height()), + *block.texture, + Rect(0, 0, block.texture->width(), block.texture->height()), + 1., + BlendMode::UseAlpha, + packed_texture.get()); textures->emplace_back(new Texture( packed_texture->get_gl_texture(), === modified file 'src/logic/map_info.cc' --- src/logic/map_info.cc 2014-11-30 13:14:18 +0000 +++ src/logic/map_info.cc 2014-12-08 05:59:46 +0000 @@ -93,7 +93,7 @@ // Write minimap { FileWrite fw; - save_surface_to_png(minimap.get(), &fw, COLOR_TYPE::RGBA); + save_to_png(minimap.get(), &fw, ColorType::RGBA); fw.write(*in_out_filesystem, (map_file + ".png").c_str()); } === modified file 'src/map_io/map_extradata_packet.cc' --- src/map_io/map_extradata_packet.cc 2014-12-08 05:59:45 +0000 +++ src/map_io/map_extradata_packet.cc 2014-12-08 05:59:46 +0000 @@ -21,7 +21,6 @@ #include "graphic/graphic.h" #include "graphic/image_io.h" -#include "graphic/in_memory_image.h" #include "graphic/texture.h" #include "io/fileread.h" #include "io/filewrite.h" @@ -59,8 +58,7 @@ const std::string hash = std::string("map:") + FileSystem::fs_filename(pname->c_str()); const Image* image = nullptr; if (!g_gr->images().has(hash)) { - image = g_gr->images().insert( - hash, new_in_memory_image(load_image(*pname, &fs).release())); + image = g_gr->images().insert(hash, load_image(*pname, &fs)); } else { image = g_gr->images().get(hash); } === modified file 'src/map_io/map_saver.cc' --- src/map_io/map_saver.cc 2014-11-30 09:17:50 +0000 +++ src/map_io/map_saver.cc 2014-12-08 05:59:46 +0000 @@ -220,7 +220,7 @@ std::unique_ptr<Texture> minimap( draw_minimap(m_egbase, nullptr, Point(0, 0), MiniMapLayer::Terrain)); FileWrite fw; - save_surface_to_png(minimap.get(), &fw, COLOR_TYPE::RGBA); + save_to_png(minimap.get(), &fw, ColorType::RGBA); fw.write(m_fs, "minimap.png"); } } === modified file 'src/ui_basic/CMakeLists.txt' --- src/ui_basic/CMakeLists.txt 2014-11-28 16:40:55 +0000 +++ src/ui_basic/CMakeLists.txt 2014-12-08 05:59:46 +0000 @@ -58,7 +58,7 @@ base_macros graphic graphic_color - graphic_image + graphic_surface io_filesystem # TODO(sirver): should not depend on logic logic === modified file 'src/ui_fsmenu/CMakeLists.txt' --- src/ui_fsmenu/CMakeLists.txt 2014-11-12 13:13:25 +0000 +++ src/ui_fsmenu/CMakeLists.txt 2014-12-08 05:59:46 +0000 @@ -45,7 +45,6 @@ build_info game_io graphic - graphic_image graphic_image_io graphic_surface helper === modified file 'src/ui_fsmenu/loadgame.cc' --- src/ui_fsmenu/loadgame.cc 2014-12-08 05:59:45 +0000 +++ src/ui_fsmenu/loadgame.cc 2014-12-08 05:59:46 +0000 @@ -34,7 +34,6 @@ #include "game_io/game_preload_packet.h" #include "graphic/graphic.h" #include "graphic/image_io.h" -#include "graphic/in_memory_image.h" #include "graphic/texture.h" #include "helper.h" #include "io/filesystem/layered_filesystem.h" @@ -316,12 +315,9 @@ if (!minimap_path.empty()) { try { // Load the image - std::unique_ptr<Texture> texture( - load_image( - minimap_path, - std::unique_ptr<FileSystem>(g_fs->make_sub_file_system(gamedata.filename)).get())); - - m_minimap_image = new_in_memory_image(texture.release()); + m_minimap_image = load_image( + minimap_path, + std::unique_ptr<FileSystem>(g_fs->make_sub_file_system(gamedata.filename)).get()); // Scale it double scale = double(m_minimap_w) / m_minimap_image->width(); === modified file 'src/wui/CMakeLists.txt' --- src/wui/CMakeLists.txt 2014-12-04 20:54:13 +0000 +++ src/wui/CMakeLists.txt 2014-12-08 05:59:46 +0000 @@ -158,7 +158,6 @@ graphic graphic_color graphic_game_renderer - graphic_image graphic_minimap_renderer graphic_surface io_fileread === modified file 'src/wui/minimap.cc' --- src/wui/minimap.cc 2014-12-08 05:59:45 +0000 +++ src/wui/minimap.cc 2014-12-08 05:59:46 +0000 @@ -23,7 +23,6 @@ #include "base/i18n.h" #include "graphic/graphic.h" -#include "graphic/in_memory_image.h" #include "graphic/minimap_renderer.h" #include "graphic/rendertarget.h" #include "graphic/texture.h" @@ -70,10 +69,7 @@ Point((m_viewx - get_w() / 4), (m_viewy - get_h() / 4)) : Point((m_viewx - get_w() / 2), (m_viewy - get_h() / 2)), *m_flags | MiniMapLayer::ViewWindow)); - // Give ownership of the texture to the new image - std::unique_ptr<const Image> im(new_in_memory_image(texture.release())); - dst.blit(Point(), im.get()); - im.reset(); + dst.blit(Point(), texture.get()); }
_______________________________________________ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp