diff --git a/src/bitmap.cpp b/src/bitmap.cpp index 2135617a22..59b8a06147 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -23,6 +23,7 @@ #include #include +#include "opacity.h" #include "pixel_format.h" #include "utils.h" #include "cache.h" @@ -546,6 +547,10 @@ void Bitmap::Init(int width, int height, void* data, int pitch, bool destroy) { if (data != NULL && destroy) pixman_image_set_destroy_function(bitmap.get(), destroy_func, data); + + if (!GetTransparent()) { + image_opacity = ImageOpacity::Opaque; + } } void Bitmap::ConvertImage(int& width, int& height, void*& pixels, bool transparent) { @@ -625,17 +630,13 @@ namespace { } // anonymous namespace void Bitmap::Blit(int x, int y, Bitmap const& src, Rect const& src_rect, Opacity const& opacity, Bitmap::BlendMode blend_mode) { - if (opacity.IsTransparent()) { + auto pixman_op = src.GetOperator(opacity, blend_mode); + + if (BitmapBlit::Blit(*this, x, y, src, src_rect, opacity, pixman_op)) { return; } auto mask = CreateMask(opacity, src_rect); - auto pixman_op = src.GetOperator(mask.get(), blend_mode); - - if (!mask && src.pixman_format == pixman_format) { - BitmapBlit::Blit(*this, x, y, src, src_rect, opacity, pixman_op); - return; - } pixman_image_composite32(pixman_op, src.bitmap.get(), @@ -647,12 +648,7 @@ void Bitmap::Blit(int x, int y, Bitmap const& src, Rect const& src_rect, Opacity } void Bitmap::BlitFast(int x, int y, Bitmap const & src, Rect const & src_rect, Opacity const & opacity) { - if (opacity.IsTransparent()) { - return; - } - - if (src.pixman_format == pixman_format) { - BitmapBlit::BlitFast(*this, x, y, src, src_rect, opacity); + if (BitmapBlit::BlitFast(*this, x, y, src, src_rect, opacity)) { return; } @@ -691,7 +687,7 @@ void Bitmap::TiledBlit(int ox, int oy, Rect const& src_rect, Bitmap const& src, auto mask = CreateMask(opacity, src_rect); - pixman_image_composite32(src.GetOperator(mask.get(), blend_mode), + pixman_image_composite32(src.GetOperator(opacity, blend_mode), src_bm.get(), mask.get(), bitmap.get(), ox, oy, 0, 0, @@ -717,7 +713,7 @@ void Bitmap::StretchBlit(Rect const& dst_rect, Bitmap const& src, Rect const& sr auto mask = CreateMask(opacity, src_rect, &xform); - pixman_image_composite32(src.GetOperator(mask.get(), blend_mode), + pixman_image_composite32(src.GetOperator(opacity, blend_mode), src.bitmap.get(), mask.get(), bitmap.get(), src_rect.x / zoom_x, src_rect.y / zoom_y, 0, 0, @@ -752,7 +748,7 @@ void Bitmap::WaverBlit(int x, int y, double zoom_x, double zoom_y, Bitmap const& const double sy = (i - yclip) * (2 * M_PI) / (32.0 * zoom_y); const int offset = 2 * zoom_x * depth * std::sin(phase + sy); - pixman_image_composite32(src.GetOperator(mask.get(), blend_mode), + pixman_image_composite32(src.GetOperator(opacity, blend_mode), src.bitmap.get(), mask.get(), bitmap.get(), xoff, yoff + i, 0, i, @@ -1234,7 +1230,7 @@ void Bitmap::RotateZoomOpacityBlit(int x, int y, int ox, int oy, // OP_SRC draws a black rectangle around the rotated image making this operator unusable here blend_mode = (blend_mode == BlendMode::Default ? BlendMode::Normal : blend_mode); - pixman_image_composite32(GetOperator(mask.get(), blend_mode), + pixman_image_composite32(GetOperator(opacity, blend_mode), src_img, mask.get(), bitmap.get(), dst_rect.x, dst_rect.y, dst_rect.x, dst_rect.y, @@ -1261,7 +1257,7 @@ void Bitmap::ZoomOpacityBlit(int x, int y, int ox, int oy, StretchBlit(dst_rect, src, src_rect, opacity, blend_mode); } -pixman_op_t Bitmap::GetOperator(pixman_image_t* mask, Bitmap::BlendMode blend_mode) const { +pixman_op_t Bitmap::GetOperator(Opacity const& opacity, Bitmap::BlendMode blend_mode) const { if (blend_mode != BlendMode::Default) { switch (blend_mode) { case BlendMode::Normal: @@ -1299,7 +1295,9 @@ pixman_op_t Bitmap::GetOperator(pixman_image_t* mask, Bitmap::BlendMode blend_mo } } - if (!mask && (!GetTransparent() || GetImageOpacity() == ImageOpacity::Opaque)) { + bool has_mask = !opacity.IsOpaque() && !opacity.IsTransparent(); + + if (!has_mask && GetImageOpacity() == ImageOpacity::Opaque) { return PIXMAN_OP_SRC; } @@ -1315,7 +1313,7 @@ void Bitmap::EdgeMirrorBlit(int x, int y, Bitmap const& src, Rect const& src_rec const auto dst_rect = GetRect(); auto draw = [&](int x, int y) { - pixman_image_composite32(src.GetOperator(mask.get()), + pixman_image_composite32(src.GetOperator(opacity), src.bitmap.get(), mask.get(), bitmap.get(), src_rect.x, src_rect.y, diff --git a/src/bitmap.h b/src/bitmap.h index f417983660..a68b39a09d 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -667,7 +667,7 @@ class Bitmap { * @param blend_mode When >= 0: Force this blend mode as operator * @return blend mode */ - pixman_op_t GetOperator(pixman_image_t* mask = nullptr, BlendMode blend_mode = BlendMode::Default) const; + pixman_op_t GetOperator(Opacity const& opacity = Opacity::Opaque(), BlendMode blend_mode = BlendMode::Default) const; bool read_only = false; }; diff --git a/src/bitmap_blit.cpp b/src/bitmap_blit.cpp index 858e234716..6bae8350c0 100644 --- a/src/bitmap_blit.cpp +++ b/src/bitmap_blit.cpp @@ -21,10 +21,6 @@ namespace { bool adjust_rects(Bitmap const& dest, Rect& dst_rect, Bitmap const& src, Rect& src_rect, Opacity const& opacity) { - if (opacity.IsTransparent()) { - return false; - } - if (!Rect::AdjustRectangles(src_rect, dst_rect, src.GetRect())) return false; @@ -34,30 +30,34 @@ bool adjust_rects(Bitmap const& dest, Rect& dst_rect, Bitmap const& src, Rect& s return true; } -void BlitFastT() { - -} - } namespace BitmapBlit { -void Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, +bool Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, Opacity const& opacity, pixman_op_t blend_mode) { if (blend_mode == PIXMAN_OP_SRC) { - BlitFast(dest, x, y, src, src_rect, opacity); - return; + return BlitFast(dest, x, y, src, src_rect, opacity); } - if (blend_mode != PIXMAN_OP_OVER) { - return; + if (opacity.IsTransparent()) { + return true; + } + + if (dest.format != src.format) { + return false; + } + + if (blend_mode != PIXMAN_OP_OVER || src.bpp() != 2) { + // Not supported + return false; } Rect dst_rect = {x, y, 0, 0}; if (!adjust_rects(dest, dst_rect, src, src_rect, opacity)) { - return; + return true; } int bpp = src.bpp(); @@ -112,16 +112,10 @@ void Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, x - bpp - run_beg); } } - - /*if (run_alpha != 0 && x - bpp >= run_beg) { - memcpy( - dst_pixels + y * dst_pitch, - src_pixels + y * src_pitch, - to_copy); - }*/ } /* + // Naive implementation for (int y = 0; y < src_rect.height; ++y) { for (int x = 0; x < src_rect.width * bpp; x += bpp) { src_pixel = *(uint16_t*)(src_pixels + y * src_pitch + x); @@ -132,15 +126,25 @@ void Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, } } */ + + return true; } -void BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, +bool BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, Opacity const& opacity) { + if (opacity.IsTransparent()) { + return true; + } + + if (dest.format != src.format) { + return false; + } + Rect dst_rect = {x, y, 0, 0}; if (!adjust_rects(dest, dst_rect, src, src_rect, opacity)) { - return; + return true; } int bpp = src.bpp(); @@ -158,6 +162,8 @@ void BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, src_pixels + y * src_pitch, to_copy); } + + return true; } } // namespace BitmapBlit diff --git a/src/bitmap_blit.h b/src/bitmap_blit.h index c249c7e2d8..8dd55a08a7 100644 --- a/src/bitmap_blit.h +++ b/src/bitmap_blit.h @@ -22,10 +22,10 @@ #include namespace BitmapBlit { - void Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, + bool Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, Opacity const& opacity, pixman_op_t blend_mode); - void BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, + bool BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect, Opacity const& opacity); } diff --git a/src/pixel_format.h b/src/pixel_format.h index 82332a2be7..2dee9157ab 100644 --- a/src/pixel_format.h +++ b/src/pixel_format.h @@ -69,11 +69,11 @@ struct Component { byte = shift / 8; } - constexpr bool operator==(const Component& c) { + constexpr bool operator==(const Component& c) const { return mask == c.mask; } - constexpr bool operator!=(const Component& c) { + constexpr bool operator!=(const Component& c) const { return mask != c.mask; } @@ -189,11 +189,11 @@ class DynamicFormat { return r.pack(_r) | g.pack(_g) | b.pack(_b) | a.pack(_a); } - constexpr bool operator==(const DynamicFormat& f) { + constexpr bool operator==(const DynamicFormat& f) const { return r == f.r && g == f.g && b == f.b && a == f.a && alpha_type == f.alpha_type; } - constexpr bool operator!=(const DynamicFormat& f) { + constexpr bool operator!=(const DynamicFormat& f) const { return r != f.r || g != f.g || b != f.b || a != f.a || alpha_type != f.alpha_type; } };