widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #03335
[Merge] lp:~widelands-dev/widelands/move_drawing_out into lp:widelands
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());
}
Follow ups