SirVer has proposed merging lp:~widelands-dev/widelands/remove_gray into lp:widelands with lp:~widelands-dev/widelands/remove_cached_resizing as a prerequisite.
Requested reviews: Widelands Developers (widelands-dev) For more details, see: https://code.launchpad.net/~widelands-dev/widelands/remove_gray/+merge/243631 Suggested commit message: - Removes all uses of ImageTransformation::change_luminosity and ::gray_out. This needed some refactoring in the how blits are done. -- Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/remove_gray into lp:widelands.
=== modified file 'src/editor/ui_menus/categorized_item_selection_menu.h' --- src/editor/ui_menus/categorized_item_selection_menu.h 2014-12-04 09:21:33 +0000 +++ src/editor/ui_menus/categorized_item_selection_menu.h 2014-12-04 09:21:33 +0000 @@ -25,7 +25,6 @@ #include "base/i18n.h" #include "graphic/image.h" -#include "graphic/image_transformations.h" #include "logic/description_maintainer.h" #include "logic/world/editor_category.h" #include "ui_basic/box.h" === 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-04 09:21:33 +0000 +++ src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc 2014-12-04 09:21:33 +0000 @@ -78,13 +78,17 @@ Texture* texture = new Texture(terrain_texture.width(), terrain_texture.height()); texture->blit(Rect(0, 0, terrain_texture.width(), terrain_texture.height()), &terrain_texture, - Rect(0, 0, terrain_texture.width(), terrain_texture.height())); + Rect(0, 0, terrain_texture.width(), terrain_texture.height()), + 1., + BlendMode::UseAlpha); 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())); + Rect(0, 0, green->width(), green->height()), + 1., + BlendMode::UseAlpha); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("arable")); @@ -92,7 +96,9 @@ 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())); + Rect(0, 0, water->width(), water->height()), + 1., + BlendMode::UseAlpha); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("aquatic")); @@ -100,7 +106,9 @@ 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())); + Rect(0, 0, mountain->width(), mountain->height()), + 1., + BlendMode::UseAlpha); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("mountainous")); @@ -108,7 +116,9 @@ 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())); + Rect(0, 0, dead->width(), dead->height()), + 1., + BlendMode::UseAlpha); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("dead")); @@ -116,7 +126,9 @@ 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())); + Rect(0, 0, unpassable->width(), unpassable->height()), + 1., + BlendMode::UseAlpha); pt.x += kSmallPicWidth + 1; /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("unpassable")); @@ -124,7 +136,9 @@ 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())); + Rect(0, 0, dry->width(), dry->height()), + 1., + BlendMode::UseAlpha); /** TRANSLATORS: This is a terrain type tooltip in the editor */ tooltips.push_back(_("treeless")); } === modified file 'src/graphic/animation.cc' --- src/graphic/animation.cc 2014-12-04 09:21:33 +0000 +++ src/graphic/animation.cc 2014-12-04 09:21:33 +0000 @@ -323,7 +323,8 @@ assert(target); const Image& frame = get_frame(time, clr); - target->blit(Rect(dst.x, dst.y, srcrc.w, srcrc.h), frame.texture(), srcrc); + target->blit( + Rect(dst.x, dst.y, srcrc.w, srcrc.h), frame.texture(), srcrc, 1., BlendMode::UseAlpha); } const Image& NonPackedAnimation::get_frame(uint32_t time, const RGBColor* playercolor) const { === modified file 'src/graphic/blend_mode.h' --- src/graphic/blend_mode.h 2014-11-24 07:25:21 +0000 +++ src/graphic/blend_mode.h 2014-12-04 09:21:33 +0000 @@ -21,7 +21,7 @@ #define WL_GRAPHIC_BLEND_MODE_H // Defines blending during blitting. -enum BlendMode { +enum class BlendMode { // Perform a normal blitting operation that respects the alpha channel if // present. UseAlpha = 0, === modified file 'src/graphic/gl/blit_program.cc' --- src/graphic/gl/blit_program.cc 2014-11-24 07:25:21 +0000 +++ src/graphic/gl/blit_program.cc 2014-12-04 09:21:33 +0000 @@ -22,6 +22,7 @@ #include <vector> #include "base/log.h" +#include "graphic/gl/utils.h" namespace { @@ -43,32 +44,87 @@ } )"; -const char kBlitFragmentShader[] = R"( -#version 120 - -uniform sampler2D u_texture; - -varying vec2 out_texture_coordinate; - -void main() { - gl_FragColor = texture2D(u_texture, out_texture_coordinate); +const char kVanillaBlitFragmentShader[] = R"( +#version 120 + +uniform float u_opacity; +uniform sampler2D u_texture; + +varying vec2 out_texture_coordinate; + +void main() { + vec4 color = texture2D(u_texture, out_texture_coordinate); + gl_FragColor = vec4(color.rgb, u_opacity * color.a); +} +)"; + +const char kGrayBlitFragmentShader[] = R"( +#version 120 + +uniform float u_luminosity_factor; +uniform float u_opacity; +uniform sampler2D u_texture; + +varying vec2 out_texture_coordinate; + +void main() { + vec4 texture_color = texture2D(u_texture, out_texture_coordinate); + // See http://en.wikipedia.org/wiki/YUV. + float luminance = dot(vec3(0.299, 0.587, 0.114), texture_color.rgb) * u_luminosity_factor; + + gl_FragColor = vec4(vec3(luminance), u_opacity * texture_color.a); } )"; } // namespace -// static -BlitProgram& BlitProgram::instance() { - static BlitProgram blit_program; - return blit_program; -} - -BlitProgram::BlitProgram() { - gl_program_.build(kBlitVertexShader, kBlitFragmentShader); +class BlitProgram { +public: + BlitProgram(const std::string& fragment_shader); + + void activate(const FloatRect& gl_dest_rect, + const FloatRect& gl_src_rect, + const GLuint gl_texture, + const float opacity, + const BlendMode blend_mode); + + void draw(); + void draw_and_deactivate(BlendMode blend_mode); + + GLuint program_object() const { + return gl_program_.object(); + } + +private: + struct PerVertexData { + float gl_x, gl_y; + }; + static_assert(sizeof(PerVertexData) == 8, "Wrong padding."); + + // The buffer that will contain the quad for rendering. + Gl::Buffer gl_array_buffer_; + + // The program. + Gl::Program gl_program_; + + // Attributes. + GLint attr_position_; + + // Uniforms. + GLint u_dst_rect_; + GLint u_opacity_; + GLint u_src_rect_; + GLint u_texture_; + DISALLOW_COPY_AND_ASSIGN(BlitProgram); +}; + +BlitProgram::BlitProgram(const std::string& fragment_shader) { + gl_program_.build(kBlitVertexShader, fragment_shader.c_str()); attr_position_ = glGetAttribLocation(gl_program_.object(), "attr_position"); u_texture_ = glGetUniformLocation(gl_program_.object(), "u_texture"); + u_opacity_ = glGetUniformLocation(gl_program_.object(), "u_opacity"); u_dst_rect_ = glGetUniformLocation(gl_program_.object(), "u_dst_rect"); u_src_rect_ = glGetUniformLocation(gl_program_.object(), "u_src_rect"); @@ -94,9 +150,10 @@ glBindBuffer(GL_ARRAY_BUFFER, 0); } -void BlitProgram::draw(const FloatRect& gl_dest_rect, +void BlitProgram::activate(const FloatRect& gl_dest_rect, const FloatRect& gl_src_rect, const GLuint gl_texture, + const float opacity, const BlendMode blend_mode) { glUseProgram(gl_program_.object()); glEnableVertexAttribArray(attr_position_); @@ -111,6 +168,7 @@ glUniform1i(u_texture_, 0); + glUniform1f(u_opacity_, opacity); glUniform4f(u_dst_rect_, gl_dest_rect.x, gl_dest_rect.y, gl_dest_rect.w, gl_dest_rect.h); glUniform4f(u_src_rect_, gl_src_rect.x, gl_src_rect.y, gl_src_rect.w, gl_src_rect.h); @@ -120,7 +178,9 @@ if (blend_mode == BlendMode::Copy) { glBlendFunc(GL_ONE, GL_ZERO); } +} +void BlitProgram::draw_and_deactivate(BlendMode blend_mode) { glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); if (blend_mode == BlendMode::Copy) { @@ -130,3 +190,53 @@ glDisableVertexAttribArray(attr_position_); glBindBuffer(GL_ARRAY_BUFFER, 0); } + +// static +VanillaBlitProgram& VanillaBlitProgram::instance() { + static VanillaBlitProgram blit_program; + return blit_program; +} + +VanillaBlitProgram::~VanillaBlitProgram() { +} + +VanillaBlitProgram::VanillaBlitProgram() { + blit_program_.reset(new BlitProgram(kVanillaBlitFragmentShader)); +} + + +void VanillaBlitProgram::draw(const FloatRect& gl_dest_rect, + const FloatRect& gl_src_rect, + const GLuint gl_texture, + const float opacity, + const BlendMode blend_mode) { + blit_program_->activate(gl_dest_rect, gl_src_rect, gl_texture, opacity, blend_mode); + blit_program_->draw_and_deactivate(blend_mode); +} + +// static +GrayBlitProgram& GrayBlitProgram::instance() { + static GrayBlitProgram blit_program; + return blit_program; +} + +GrayBlitProgram::~GrayBlitProgram() { +} + +GrayBlitProgram::GrayBlitProgram() { + blit_program_.reset(new BlitProgram(kGrayBlitFragmentShader)); + + u_luminosity_factor_ = glGetUniformLocation(blit_program_->program_object(), "u_luminosity_factor"); +} + +void GrayBlitProgram::draw(const FloatRect& gl_dest_rect, + const FloatRect& gl_src_rect, + const GLuint gl_texture, + const float opacity, + const float luminosity_factor) { + blit_program_->activate(gl_dest_rect, gl_src_rect, gl_texture, opacity, BlendMode::UseAlpha); + + glUniform1f(u_luminosity_factor_, luminosity_factor); + + blit_program_->draw_and_deactivate(BlendMode::UseAlpha); +} === modified file 'src/graphic/gl/blit_program.h' --- src/graphic/gl/blit_program.h 2014-11-24 07:25:21 +0000 +++ src/graphic/gl/blit_program.h 2014-12-04 09:21:33 +0000 @@ -20,49 +20,67 @@ #ifndef WL_GRAPHIC_GL_BLIT_PROGRAM_H #define WL_GRAPHIC_GL_BLIT_PROGRAM_H +#include <memory> + +#include "base/macros.h" #include "base/rect.h" #include "graphic/blend_mode.h" #include "graphic/color.h" -#include "graphic/gl/utils.h" - -class BlitProgram { -public: - // Returns the (singleton) instance of this class. - static BlitProgram& instance(); +#include "graphic/gl/system_headers.h" + +class BlitProgram; + +class VanillaBlitProgram { +public: + // Returns the (singleton) instance of this class. + static VanillaBlitProgram& instance(); + ~VanillaBlitProgram(); + + // Draws the rectangle 'gl_src_rect' from the texture with the name + // 'gl_texture' to 'gl_dest_rect' in the currently bound framebuffer. All alpha + // values are multiplied by 'opacity' during the blit. + // All coordinates are in the OpenGL frame. The 'blend_mode' defines if the + // values are copied or if alpha values are used. + void draw(const FloatRect& gl_dest_rect, + const FloatRect& gl_src_rect, + const GLuint gl_texture, + float opacity, + const BlendMode blend_mode); + +private: + VanillaBlitProgram(); + + std::unique_ptr<BlitProgram> blit_program_; + + DISALLOW_COPY_AND_ASSIGN(VanillaBlitProgram); +}; + +class GrayBlitProgram { +public: + // Returns the (singleton) instance of this class. + static GrayBlitProgram& instance(); + ~GrayBlitProgram(); // Draws the rectangle 'gl_src_rect' from the texture with the name // 'gl_texture' to 'gl_dest_rect' in the currently bound framebuffer. All // coordinates are in the OpenGL frame. The 'blend_mode' defines if the // values are copied or if alpha values are used. + // The image is converted to grayscale during blit. void draw(const FloatRect& gl_dest_rect, const FloatRect& gl_src_rect, const GLuint gl_texture, - const BlendMode blend_mode); + float opacity, + float luminosity_factor); private: - BlitProgram(); - - struct PerVertexData { - float gl_x, gl_y; - }; - static_assert(sizeof(PerVertexData) == 8, "Wrong padding."); - - // The buffer that will contain the quad for rendering. - Gl::Buffer gl_array_buffer_; - - // The program. - Gl::Program gl_program_; - - // Attributes. - GLint attr_position_; + GrayBlitProgram(); + + std::unique_ptr<BlitProgram> blit_program_; // Uniforms. - GLint u_texture_; - GLint u_dst_rect_; - GLint u_src_rect_; + GLint u_luminosity_factor_; - DISALLOW_COPY_AND_ASSIGN(BlitProgram); + DISALLOW_COPY_AND_ASSIGN(GrayBlitProgram); }; - #endif // end of include guard: WL_GRAPHIC_GL_DRAW_RECT_PROGRAM_H === modified file 'src/graphic/image_transformations.cc' --- src/graphic/image_transformations.cc 2014-12-04 09:21:33 +0000 +++ src/graphic/image_transformations.cc 2014-12-04 09:21:33 +0000 @@ -39,120 +39,6 @@ uint32_t luminance_table_g[0x100]; uint32_t luminance_table_b[0x100]; -/** - * Create and return an \ref SDL_Surface that contains the given sub-rectangle - * of the given pixel region. - */ -SDL_Surface* extract_sdl_surface(Texture & texture, Rect srcrect) -{ - assert(srcrect.x >= 0); - assert(srcrect.y >= 0); - assert(srcrect.x + srcrect.w <= texture.width()); - assert(srcrect.y + srcrect.h <= texture.height()); - - const SDL_PixelFormat & fmt = texture.format(); - SDL_Surface * dest = SDL_CreateRGBSurface - (SDL_SWSURFACE, srcrect.w, srcrect.h, - fmt.BitsPerPixel, fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask); - - texture.lock(Surface::Lock_Normal); - SDL_LockSurface(dest); - - uint32_t srcpitch = texture.get_pitch(); - uint32_t rowsize = srcrect.w * fmt.BytesPerPixel; - uint8_t * srcpix = texture.get_pixels() + srcpitch * srcrect.y + fmt.BytesPerPixel * srcrect.x; - uint8_t * dstpix = static_cast<uint8_t *>(dest->pixels); - - for (int y = 0; y < srcrect.h; ++y) { - memcpy(dstpix, srcpix, rowsize); - srcpix += srcpitch; - dstpix += dest->pitch; - } - - SDL_UnlockSurface(dest); - texture.unlock(Surface::Unlock_NoChange); - - return dest; -} - -/** - * Create a grayed version of the given texture. - */ -Texture* gray_out_texture(Texture* texture) { - assert(texture); - - uint16_t w = texture->width(); - uint16_t h = texture->height(); - const SDL_PixelFormat & origfmt = texture->format(); - - Texture* dest = new Texture(w, h); - const SDL_PixelFormat & destfmt = dest->format(); - - texture->lock(Surface::Lock_Normal); - dest->lock(Surface::Lock_Discard); - for (uint32_t y = 0; y < h; ++y) { - for (uint32_t x = 0; x < w; ++x) { - RGBAColor color; - - color.set(origfmt, texture->get_pixel(x, y)); - - // Halve the opacity to give some difference for image that are - // grayscale to begin with. - color.a >>= 1; - - color.r = color.g = color.b = - (luminance_table_r[color.r] + - luminance_table_g[color.g] + - luminance_table_b[color.b] + - 8388608U) // compensate for truncation: .5 * 2^24 - >> 24; - - dest->set_pixel(x, y, color.map(destfmt)); - } - } - texture->unlock(Surface::Unlock_NoChange); - dest->unlock(Surface::Unlock_Update); - - return dest; -} - -/** - * Creates an image with changed luminosity from the given texture. - */ -Texture* change_luminosity_of_texture(Texture* texture, float factor, bool halve_alpha) { - assert(texture); - - uint16_t w = texture->width(); - uint16_t h = texture->height(); - const SDL_PixelFormat & origfmt = texture->format(); - - Texture* dest = new Texture(w, h); - const SDL_PixelFormat & destfmt = dest->format(); - - texture->lock(Surface::Lock_Normal); - dest->lock(Surface::Lock_Discard); - for (uint32_t y = 0; y < h; ++y) { - for (uint32_t x = 0; x < w; ++x) { - RGBAColor color; - - color.set(origfmt, texture->get_pixel(x, y)); - - if (halve_alpha) - color.a >>= 1; - - color.r = color.r * factor > 255 ? 255 : color.r * factor; - color.g = color.g * factor > 255 ? 255 : color.g * factor; - color.b = color.b * factor > 255 ? 255 : color.b * factor; - - dest->set_pixel(x, y, color.map(destfmt)); - } - } - texture->unlock(Surface::Unlock_NoChange); - dest->unlock(Surface::Unlock_Update); - - return dest; -} - // Encodes the given Image into the corresponding image for player color. // Takes the neutral set of images and the player color mask. Texture* make_playerclr_texture(Texture& original_texture, @@ -246,42 +132,6 @@ TextureCache* const texture_cache_; // not owned }; -// A grayed out copy of an Image. -class GrayedOutImage : public TransformedImage { -public: - GrayedOutImage(const string& ghash, const Image& original, TextureCache* texture_cache) : - TransformedImage(ghash, original, texture_cache) - {} - virtual ~GrayedOutImage() {} - - // Implements TransformedImage. - Texture* recalculate_texture() const override { - return gray_out_texture(original_.texture()); - } -}; - -// A copy with another luminosity and maybe half the opacity. -class ChangeLuminosityImage : public TransformedImage { -public: - ChangeLuminosityImage - (const string& ghash, const Image& original, - TextureCache* texture_cache, float factor, bool halve_alpha) - : TransformedImage(ghash, original, texture_cache), - factor_(factor), - halve_alpha_(halve_alpha) - {} - virtual ~ChangeLuminosityImage() {} - - // Implements TransformedImage. - Texture* recalculate_texture() const override { - return change_luminosity_of_texture(original_.texture(), factor_, halve_alpha_); - } - -private: - float factor_; - bool halve_alpha_; -}; - // A copy with applied player colors. Also needs a mask - ownership is not // taken. class PlayerColoredImage : public TransformedImage { @@ -320,24 +170,6 @@ } } -const Image* gray_out(const Image* original) { - const string new_hash = original->hash() + ":greyed_out"; - if (g_gr->images().has(new_hash)) - return g_gr->images().get(new_hash); - return - g_gr->images().insert(new GrayedOutImage(new_hash, *original, &g_gr->textures())); -} - -const Image* change_luminosity(const Image* original, float factor, bool halve_alpha) { - const string new_hash = - (boost::format("%s:%i:%i") % original->hash() % static_cast<int>(factor * 1000) % halve_alpha).str(); - if (g_gr->images().has(new_hash)) - return g_gr->images().get(new_hash); - return - g_gr->images().insert - (new ChangeLuminosityImage(new_hash, *original, &g_gr->textures(), factor, halve_alpha)); -} - const Image* player_colored(const RGBColor& clr, const Image* original, const Image* mask) { const string new_hash = (boost::format("%s:%02x%02x%02x") % original->hash() % static_cast<int>(clr.r) % === modified file 'src/graphic/image_transformations.h' --- src/graphic/image_transformations.h 2014-12-04 09:21:33 +0000 +++ src/graphic/image_transformations.h 2014-12-04 09:21:33 +0000 @@ -37,14 +37,6 @@ // safe to call the methods with the same arguments multiple times without // construction cost. -// Returns a grayed out image of the original. -const Image* gray_out(const Image* original); - -// Returns an image with a modified luminosity by 'factor' and alpha value than -// the original. If 'halve_alpha' is true, the opacity will be halfed, -// otherwise it will not be touched. -const Image* change_luminosity(const Image* original, float factor, bool halve_alpha); - // Encodes the given Image into the corresponding image with a player color. // Takes the image and the player color mask and the new color the image should // be tainted in. === modified file 'src/graphic/rendertarget.cc' --- src/graphic/rendertarget.cc 2014-12-04 09:21:33 +0000 +++ src/graphic/rendertarget.cc 2014-12-04 09:21:33 +0000 @@ -23,7 +23,6 @@ #include "base/macros.h" #include "graphic/animation.h" #include "graphic/graphic.h" -#include "graphic/image_transformations.h" #include "graphic/surface.h" #include "logic/player.h" #include "logic/tribe.h" @@ -173,11 +172,11 @@ 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, - blend_mode); + m_surface->blit(Rect(destination_point.x, destination_point.y, srcrc.w, srcrc.h), + image->texture(), + srcrc, + 1., + blend_mode); } } @@ -199,28 +198,47 @@ 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, - blend_mode); + m_surface->blit(Rect(destination_point.x, destination_point.y, srcrc.w, srcrc.h), + image->texture(), + srcrc, + 1., + blend_mode); } void RenderTarget::blitrect_scale(const Rect& dst, const Image* image, - const Rect& src, + const Rect& source_rect, + const float opacity, const BlendMode blend_mode) { Point destination_point(dst.x, dst.y); - Rect srcrect(src); + 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(), - src, + source_rect, + opacity, blend_mode); } } +void RenderTarget::blitrect_scale_gray(const Rect& destination_rect, + const Image* image, + const Rect& source_rect, + float opacity, + float luminosity_factor) { + Point destination_point(destination_rect.x, destination_rect.y); + Rect srcrect(source_rect); + if (to_surface_geometry(&destination_point, &srcrect)) { + m_surface->blit_gray( + Rect(destination_point.x, destination_point.y, destination_rect.w, destination_rect.h), + image->texture(), + source_rect, + opacity, + luminosity_factor); + } +} + /** * Fill the given rectangle with the given image. * @@ -274,7 +292,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, blend_mode); + m_surface->blit(dst_rect, image->texture(), srcrc, 1., blend_mode); tx += srcrc.w; === modified file 'src/graphic/rendertarget.h' --- src/graphic/rendertarget.h 2014-12-04 09:21:33 +0000 +++ src/graphic/rendertarget.h 2014-12-04 09:21:33 +0000 @@ -76,11 +76,26 @@ const Rect& src, BlendMode blend_mode = BlendMode::UseAlpha); - void blitrect_scale( - const Rect& dst, - const Image* image, - const Rect& src, - BlendMode blend_mode = BlendMode::UseAlpha); + // Blits the 'source_rect' from 'image' into the + // 'destination_rect' in this rendertarget. All alpha values are + // multiplied with 'opacity' before blitting. The 'blend_mode' + // defines if values are blended with whats already there or just + // copied over. + void blitrect_scale(const Rect& destination_rect, + const Image* image, + const Rect& source_rect, + float opacity, + BlendMode blend_mode); + + // Like blitrect_scale, but the image is converted to grayscale + // and all grayscale values are multiplied with + // 'luminosity_factor' to make the image brighter or darker. Alpha + // is always used on blending. + void blitrect_scale_gray(const Rect& destination_rect, + const Image* image, + const Rect& source_rect, + float opacity, + float luminosity_factor); void tile(const Rect&, const Image* image, === modified file 'src/graphic/surface.cc' --- src/graphic/surface.cc 2014-12-04 09:21:33 +0000 +++ src/graphic/surface.cc 2014-12-04 09:21:33 +0000 @@ -157,39 +157,59 @@ *y = (*y / height); } -void Surface::blit - (const Rect& dst, const Texture* texture, const Rect& srcrc, BlendMode blend_mode) -{ - glViewport(0, 0, width(), 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) { // 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. - FloatRect gl_src_rect; - { - const FloatRect& texture_coordinates = texture->texture_coordinates(); - - float x1 = srcrc.x; - float y1 = srcrc.y; - pixel_to_gl_texture(texture->width(), texture->height(), &x1, &y1); - x1 = texture_coordinates.x + x1 * texture_coordinates.w; - y1 = texture_coordinates.y + y1 * texture_coordinates.h; - - float x2 = srcrc.x + srcrc.w; - float y2 = srcrc.y + srcrc.h; - pixel_to_gl_texture(texture->width(), texture->height(), &x2, &y2); - x2 = texture_coordinates.x + x2 * texture_coordinates.w; - y2 = texture_coordinates.y + y2 * texture_coordinates.h; - - gl_src_rect.x = x1; - gl_src_rect.y = y1; - gl_src_rect.w = x2 - x1; - gl_src_rect.h = y2 - y1; - } - - const FloatRect gl_dst_rect = - to_opengl(Rect(dst.x, dst.y, dst.w, dst.h), ConversionMode::kExact); - - BlitProgram::instance().draw(gl_dst_rect, gl_src_rect, texture->get_gl_texture(), blend_mode); + const FloatRect& texture_coordinates = texture->texture_coordinates(); + + float x1 = src_rect.x; + float y1 = src_rect.y; + pixel_to_gl_texture(texture->width(), texture->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); + x2 = texture_coordinates.x + x2 * texture_coordinates.w; + y2 = texture_coordinates.y + y2 * texture_coordinates.h; + + gl_src_rect->x = x1; + gl_src_rect->y = y1; + 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_gray(const Rect& dst_rect, + const Texture* texture, + const Rect& src_rect, + const float opacity, + float opacity_factor) { + 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); + + GrayBlitProgram::instance().draw( + gl_dst_rect, gl_src_rect, texture->get_gl_texture(), opacity, opacity_factor); } === modified file 'src/graphic/surface.h' --- src/graphic/surface.h 2014-12-04 09:21:33 +0000 +++ src/graphic/surface.h 2014-12-04 09:21:33 +0000 @@ -46,7 +46,15 @@ virtual void blit(const Rect& dst, const Texture*, const Rect& srcrc, - BlendMode blend_mode = BlendMode::UseAlpha); + const float opacity, + BlendMode blend_mode); + + /// This draws a grayed out version. + virtual void blit_gray(const Rect& dst, + const Texture*, + const Rect& srcrc, + const float opacity, + float opacity_factor); /// 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). @@ -60,7 +68,6 @@ (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). - /// @note this is slow in SDL mode. Use with care virtual void brighten_rect(const Rect&, int32_t factor); /// The functions below are for direct pixel access. This should be used @@ -143,6 +150,14 @@ }; 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; === modified file 'src/graphic/text/rt_render.cc' --- src/graphic/text/rt_render.cc 2014-12-04 09:21:33 +0000 +++ src/graphic/text/rt_render.cc 2014-12-04 09:21:33 +0000 @@ -336,6 +336,7 @@ rv->blit(Rect(0, 0, img.width(), img.height()), &img, Rect(0, 0, img.width(), img.height()), + 1., BlendMode::Copy); return rv; } @@ -364,7 +365,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, BlendMode::Copy); + rv->blit(Rect(curx, 0, srcrect.w, srcrect.h), &t, srcrect, 1., BlendMode::Copy); } return rv; } @@ -433,7 +434,7 @@ 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, BlendMode::Copy); + rv->blit(dst, m_bg->texture(), srcrect, 1., BlendMode::Copy); } } else { rv->fill_rect(Rect(0, 0, m_w, m_h), RGBAColor(255, 255, 255, 0)); @@ -494,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, BlendMode::Copy); + rv->blit(dst, m_bg_img->texture(), src, 1., BlendMode::Copy); } } set_alpha = false; @@ -509,7 +510,7 @@ node_texture->height()); Rect src = Rect(0, 0, node_texture->width(), node_texture->height()); - rv->blit(dst, node_texture, src, set_alpha ? BlendMode::Copy : BlendMode::UseAlpha); + rv->blit(dst, node_texture, src, 1., set_alpha ? BlendMode::Copy : BlendMode::UseAlpha); delete node_texture; } delete n; @@ -563,6 +564,7 @@ rv->blit(Rect(0, 0, m_image.width(), m_image.height()), m_image.texture(), Rect(0, 0, m_image.width(), m_image.height()), + 1., BlendMode::Copy); return rv; } === modified file 'src/graphic/texture.cc' --- src/graphic/texture.cc 2014-12-04 09:21:33 +0000 +++ src/graphic/texture.cc 2014-12-04 09:21:33 +0000 @@ -265,13 +265,27 @@ } void Texture::blit - (const Rect& dst, const Texture* src, const Rect& srcrc, BlendMode blend_mode) + (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, blend_mode); + Surface::blit(dst, src, srcrc, opacity, blend_mode); + reset_gl(); +} + +void Texture::blit_gray(const Rect& dst, + const Texture* src, + const Rect& srcrc, + float opacity, + const float opacity_factor) { + if (m_w <= 0 || m_h <= 0) { + return; + } + + setup_gl(m_texture); + Surface::blit_gray(dst, src, srcrc, opacity, opacity_factor); reset_gl(); } === modified file 'src/graphic/texture.h' --- src/graphic/texture.h 2014-12-04 09:21:33 +0000 +++ src/graphic/texture.h 2014-12-04 09:21:33 +0000 @@ -61,7 +61,13 @@ void blit(const Rect& dstretc, const Texture*, const Rect& srcrc, - BlendMode blend_mode = BlendMode::UseAlpha) override; + float opacity, + BlendMode blend_mode) override; + void blit_gray(const Rect& dst, + const Texture*, + const Rect& srcrc, + const float opacity, + float opacity_factor) override; GLuint get_gl_texture() const {return m_texture;} === modified file 'src/graphic/texture_atlas.cc' --- src/graphic/texture_atlas.cc 2014-12-04 09:21:33 +0000 +++ src/graphic/texture_atlas.cc 2014-12-04 09:21:33 +0000 @@ -144,7 +144,10 @@ 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())); + Rect(0, 0, block.texture->width(), block.texture->height()), + 1., + BlendMode::UseAlpha); + textures->emplace_back(new Texture( packed_texture->get_gl_texture(), Rect(block.node->r.top_left(), block.texture->width(), block.texture->height()), === modified file 'src/logic/warehouse.cc' --- src/logic/warehouse.cc 2014-11-30 18:49:38 +0000 +++ src/logic/warehouse.cc 2014-12-04 09:21:33 +0000 @@ -376,7 +376,6 @@ (owner().is_worker_type_allowed(worker_index) && m_next_worker_without_cost_spawn[i] == static_cast<uint32_t>(never())) { - upcast(Game, game, &egbase); if (next_spawn == static_cast<uint32_t>(never())) { next_spawn = schedule_act(dynamic_cast<Game&>(egbase), WORKER_WITHOUT_COST_SPAWN_INTERVAL); } === modified file 'src/ui_basic/button.cc' --- src/ui_basic/button.cc 2014-12-04 09:21:33 +0000 +++ src/ui_basic/button.cc 2014-12-04 09:21:33 +0000 @@ -23,7 +23,6 @@ #include "graphic/font.h" #include "graphic/font_handler.h" #include "graphic/image.h" -#include "graphic/image_transformations.h" #include "graphic/rendertarget.h" #include "ui_basic/mouse_constants.h" #include "wlapplication.h" @@ -56,7 +55,6 @@ m_title (title_text), m_pic_background(bg_pic), m_pic_custom (nullptr), - m_pic_custom_disabled(nullptr), m_font(UI::Font::ui_small()), m_clr_down (229, 161, 2), m_draw_caret (false) @@ -84,7 +82,6 @@ m_time_nextact (0), m_pic_background(bg_pic), m_pic_custom (fg_pic), - m_pic_custom_disabled(fg_pic ? ImageTransformations::gray_out(fg_pic) : nullptr), m_font(UI::Font::ui_small()), m_clr_down (229, 161, 2), m_draw_caret (false) @@ -109,7 +106,6 @@ return; m_pic_custom = pic; - m_pic_custom_disabled = ImageTransformations::gray_out(pic); update(); } @@ -181,10 +177,21 @@ int blit_width = image_scale * m_pic_custom->width(); int blit_height = image_scale * m_pic_custom->height(); + if (m_enabled) { dst.blitrect_scale( Rect((get_w() - blit_width) / 2, (get_h() - blit_height) / 2, blit_width, blit_height), - m_enabled ? m_pic_custom : m_pic_custom_disabled, - Rect(0, 0, m_pic_custom->width(), m_pic_custom->height())); + m_pic_custom, + Rect(0, 0, m_pic_custom->width(), m_pic_custom->height()), + 1., + BlendMode::UseAlpha); + } else { + dst.blitrect_scale_gray( + Rect((get_w() - blit_width) / 2, (get_h() - blit_height) / 2, blit_width, blit_height), + m_pic_custom, + Rect(0, 0, m_pic_custom->width(), m_pic_custom->height()), + 0.5 /* opacity */, + 1. /* luminosity_factor */); + } } else if (m_title.length()) { // otherwise draw title string centered === modified file 'src/ui_basic/button.h' --- src/ui_basic/button.h 2014-07-14 10:45:44 +0000 +++ src/ui_basic/button.h 2014-12-04 09:21:33 +0000 @@ -105,7 +105,6 @@ const Image* m_pic_background; // background texture (picture ID) const Image* m_pic_custom; // custom icon on the button - const Image* m_pic_custom_disabled; Font * m_font; RGBColor m_clr_down; // color of border while a flat button is "down" === modified file 'src/ui_basic/icon.cc' --- src/ui_basic/icon.cc 2014-12-04 09:21:33 +0000 +++ src/ui_basic/icon.cc 2014-12-04 09:21:33 +0000 @@ -64,8 +64,11 @@ int height = scale * get_h(); int x = (get_w() - width) / 2; int y = (get_h() - height) / 2; - dst.blitrect_scale( - Rect(x, y, width, height), m_pic, Rect(0, 0, m_pic->width(), m_pic->height())); + dst.blitrect_scale(Rect(x, y, width, height), + m_pic, + Rect(0, 0, m_pic->width(), m_pic->height()), + 1., + BlendMode::UseAlpha); } if (m_draw_frame) { dst.draw_rect(Rect(0, 0, get_w(), get_h()), m_framecolor); === modified file 'src/ui_basic/progresswindow.cc' --- src/ui_basic/progresswindow.cc 2014-12-04 09:21:33 +0000 +++ src/ui_basic/progresswindow.cc 2014-12-04 09:21:33 +0000 @@ -67,7 +67,8 @@ m_label_rectangle.h = h + 2 * PROGRESS_STATUS_RECT_PADDING; const Image* bg = g_gr->images().get(m_background); - rt.blitrect_scale(Rect(0, 0, xres, yres), bg, Rect(0, 0, bg->width(), bg->height())); + rt.blitrect_scale( + Rect(0, 0, xres, yres), bg, Rect(0, 0, bg->width(), bg->height()), 1., BlendMode::UseAlpha); Rect border_rect = m_label_rectangle; border_rect.x -= PROGRESS_STATUS_BORDER_X; === modified file 'src/ui_basic/tabpanel.cc' --- src/ui_basic/tabpanel.cc 2014-12-04 09:21:33 +0000 +++ src/ui_basic/tabpanel.cc 2014-12-04 09:21:33 +0000 @@ -246,7 +246,9 @@ picture_width, picture_height), m_tabs[idx]->pic, - Rect(0, 0, m_tabs[idx]->pic->width(), m_tabs[idx]->pic->height())); + Rect(0, 0, m_tabs[idx]->pic->width(), m_tabs[idx]->pic->height()), + 1., + BlendMode::UseAlpha); // Draw top part of border RGBColor black(0, 0, 0); === modified file 'src/ui_fsmenu/base.cc' --- src/ui_fsmenu/base.cc 2014-12-04 09:21:33 +0000 +++ src/ui_fsmenu/base.cc 2014-12-04 09:21:33 +0000 @@ -66,7 +66,11 @@ */ void FullscreenMenuBase::draw(RenderTarget & dst) { const Image* bg = g_gr->images().get(background_image_); - dst.blitrect_scale(Rect(0, 0, get_w(), get_h()), bg, Rect(0, 0, bg->width(), bg->height())); + dst.blitrect_scale(Rect(0, 0, get_w(), get_h()), + bg, + Rect(0, 0, bg->width(), bg->height()), + 1., + BlendMode::UseAlpha); } uint32_t FullscreenMenuBase::fs_small() { === modified file 'src/ui_fsmenu/editor.h' --- src/ui_fsmenu/editor.h 2014-12-04 06:35:12 +0000 +++ src/ui_fsmenu/editor.h 2014-12-04 09:21:33 +0000 @@ -33,7 +33,9 @@ public: FullscreenMenuEditor(); - enum class MenuTarget { kBack = UI::Panel::dying_code, kNewMap, kLoadMap }; + enum class MenuTarget { + kBack = UI::Panel::dying_code, kNewMap, kLoadMap + }; private: UI::Textarea title; === modified file 'src/ui_fsmenu/loadgame.cc' --- src/ui_fsmenu/loadgame.cc 2014-12-04 09:21:33 +0000 +++ src/ui_fsmenu/loadgame.cc 2014-12-04 09:21:33 +0000 @@ -34,7 +34,6 @@ #include "game_io/game_preload_packet.h" #include "graphic/graphic.h" #include "graphic/image_io.h" -#include "graphic/image_transformations.h" #include "graphic/in_memory_image.h" #include "graphic/texture.h" #include "helper.h" === modified file 'src/wui/buildingwindow.cc' --- src/wui/buildingwindow.cc 2014-11-30 18:49:38 +0000 +++ src/wui/buildingwindow.cc 2014-12-04 09:21:33 +0000 @@ -24,7 +24,6 @@ #include "base/macros.h" #include "graphic/graphic.h" #include "graphic/image.h" -#include "graphic/image_transformations.h" #include "graphic/rendertarget.h" #include "logic/constructionsite.h" #include "logic/dismantlesite.h" @@ -117,9 +116,17 @@ const Animation& anim = g_gr->animations().get_animation(building().get_ui_anim()); - const Image* dark_frame = ImageTransformations::change_luminosity - (&anim.representative_image(building().owner().get_playercolor()), 1.22, true); - dst.blit(Point(get_inner_w() / 2, get_inner_h() / 2), dark_frame, BlendMode::UseAlpha, UI::Align_Center); + const Image* image = + &anim.representative_image(building().owner().get_playercolor()); + + dst.blitrect_scale(Rect((get_inner_w() - image->width()) / 2, + (get_inner_h() - image->height()) / 2, + image->width(), + image->height()), + image, + Rect(0, 0, image->width(), image->height()), + 0.5, + BlendMode::UseAlpha); } /* === modified file 'src/wui/fieldaction.cc' --- src/wui/fieldaction.cc 2014-12-04 09:21:33 +0000 +++ src/wui/fieldaction.cc 2014-12-04 09:21:33 +0000 @@ -25,7 +25,6 @@ #include "economy/flag.h" #include "economy/road.h" #include "graphic/graphic.h" -#include "graphic/image_transformations.h" #include "logic/attackable.h" #include "logic/cmd_queue.h" #include "logic/maphollowregion.h" === modified file 'src/wui/waresqueuedisplay.cc' --- src/wui/waresqueuedisplay.cc 2014-11-22 10:18:20 +0000 +++ src/wui/waresqueuedisplay.cc 2014-12-04 09:21:33 +0000 @@ -24,7 +24,6 @@ #include "economy/request.h" #include "economy/wares_queue.h" #include "graphic/graphic.h" -#include "graphic/image_transformations.h" #include "graphic/rendertarget.h" #include "logic/player.h" #include "wui/interactive_gamebase.h" @@ -63,7 +62,6 @@ set_tooltip(ware.descname().c_str()); m_icon = ware.icon(); - m_icon_grey = ImageTransformations::change_luminosity(ImageTransformations::gray_out(m_icon), 0.65, false); uint16_t ph = m_max_fill_indicator->height(); @@ -143,10 +141,22 @@ point.x = Border + (m_show_only ? 0 : CellWidth + CellSpacing); point.y = Border + (m_total_height - 2 * Border - WARE_MENU_PIC_HEIGHT) / 2; - for (; nr_wares_to_draw; --nr_wares_to_draw, point.x += CellWidth + CellSpacing) - dst.blit(point, m_icon); - for (; nr_empty_to_draw; --nr_empty_to_draw, point.x += CellWidth + CellSpacing) - dst.blit(point, m_icon_grey); + for (; nr_wares_to_draw; --nr_wares_to_draw, point.x += CellWidth + CellSpacing) { + dst.blitrect_scale( + Rect(point.x, point.y, m_icon->width(), m_icon->height()), + m_icon, + Rect(0, 0, m_icon->width(), m_icon->height()), + 1.0, + BlendMode::UseAlpha); + } + for (; nr_empty_to_draw; --nr_empty_to_draw, point.x += CellWidth + CellSpacing) { + dst.blitrect_scale_gray( + Rect(point.x, point.y, m_icon->width(), m_icon->height()), + m_icon, + Rect(0, 0, m_icon->width(), m_icon->height()), + 0.5, + 0.65); + } if (!m_show_only) { uint16_t pw = m_max_fill_indicator->width(); === modified file 'src/wui/waresqueuedisplay.h' --- src/wui/waresqueuedisplay.h 2014-11-22 10:18:20 +0000 +++ src/wui/waresqueuedisplay.h 2014-12-04 09:21:33 +0000 @@ -78,7 +78,6 @@ Widelands::WareIndex m_ware_index; Widelands::WareWorker m_ware_type; const Image* m_icon; //< Index to ware's picture - const Image* m_icon_grey; const Image* m_max_fill_indicator;
_______________________________________________ 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