From 21413b187240e0c90a0ed8a76f085123521dc18a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 25 Aug 2023 13:12:23 +0900 Subject: [PATCH] sw_engine: optimizing the masking feature replaced 32-bit operations with 8-bit operations for masking buffers. We might need a grasycale image support for applying 1-byte channel masking input(Picture). Some of masking implementation are disabled by this reason. Also, I don't expecct it's necessary for the thorvg now. --- src/examples/MaskingMethods.cpp | 365 +++++++++++++++----------- src/lib/sw_engine/tvgSwCommon.h | 3 +- src/lib/sw_engine/tvgSwRaster.cpp | 314 ++++++++++++---------- src/lib/sw_engine/tvgSwRasterTexmap.h | 30 ++- src/lib/tvgRender.h | 9 +- 5 files changed, 405 insertions(+), 316 deletions(-) diff --git a/src/examples/MaskingMethods.cpp b/src/examples/MaskingMethods.cpp index 3a924e00..164d61fe 100644 --- a/src/examples/MaskingMethods.cpp +++ b/src/examples/MaskingMethods.cpp @@ -47,27 +47,34 @@ void tvgDrawCmds(tvg::Canvas* canvas) { //Shape + Shape Mask Add auto shape = tvg::Shape::gen(); - shape->appendCircle(125, 100, 50, 50); + shape->appendCircle(125, 100, 150, 150); shape->fill(255, 255, 255); auto mask = tvg::Shape::gen(); - mask->appendCircle(175, 100, 50, 50); + mask->appendCircle(125, 100, 50, 50); mask->fill(255, 255, 255); - shape->composite(std::move(mask), tvg::CompositeMethod::AddMask); + auto add = tvg::Shape::gen(); + add->appendCircle(175, 100, 50, 50); + add->fill(255, 255, 255); + mask->composite(std::move(add), tvg::CompositeMethod::AddMask); + shape->composite(std::move(mask), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(shape)); //Shape + Shape Mask Subtract auto shape2 = tvg::Shape::gen(); - shape2->appendCircle(375, 100, 50, 50); - shape2->fill(255, 255, 255, 127); + shape2->appendCircle(375, 100, 150, 150); + shape2->fill(255, 255, 255, 255); auto mask2 = tvg::Shape::gen(); - mask2->appendCircle(400, 100, 50, 50); - mask2->fill(255, 255, 255); - - shape2->composite(std::move(mask2), tvg::CompositeMethod::SubtractMask); + mask2->appendCircle(375, 100, 50, 50); + mask2->fill(255, 255, 255, 127); + auto sub = tvg::Shape::gen(); + sub->appendCircle(400, 100, 50, 50); + sub->fill(255, 255, 255); + mask2->composite(std::move(sub), tvg::CompositeMethod::SubtractMask); + shape2->composite(std::move(mask2), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(shape2)); //Shape + Shape Mask Intersect @@ -76,125 +83,160 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape3->fill(255, 255, 255, 127); auto mask3 = tvg::Shape::gen(); - mask3->appendCircle(650, 100, 50, 50); - mask3->fill(255, 255, 255); - shape3->composite(std::move(mask3), tvg::CompositeMethod::IntersectMask); + mask3->appendCircle(625, 100, 50, 50); + mask3->fill(255, 255, 255, 127); + auto inter = tvg::Shape::gen(); + inter->appendCircle(650, 100, 50, 50); + inter->fill(255, 255, 255); + mask3->composite(std::move(inter), tvg::CompositeMethod::IntersectMask); + shape3->composite(std::move(mask3), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(shape3)); //Shape + Shape Mask Difference auto shape4 = tvg::Shape::gen(); - shape4->appendCircle(875, 100, 50, 50); + shape4->appendCircle(875, 100, 150, 150); shape4->fill(255, 255, 255); auto mask4 = tvg::Shape::gen(); - mask4->appendCircle(900, 100, 50, 50); + mask4->appendCircle(875, 100, 50, 50); mask4->fill(255, 255, 255); - shape4->composite(std::move(mask4), tvg::CompositeMethod::DifferenceMask); + auto diff = tvg::Shape::gen(); + diff->appendCircle(900, 100, 50, 50); + diff->fill(255, 255, 255); + mask4->composite(std::move(diff), tvg::CompositeMethod::DifferenceMask); + shape4->composite(std::move(mask4), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(shape4)); } - { - //Shape + Image Mask Add + //Shape + Shape Mask Add auto shape = tvg::Shape::gen(); - shape->appendCircle(150, 250, 50, 50); - shape->fill(255, 255, 255); - - auto mask = tvg::Picture::gen(); - if (mask->load(data, 200, 300, true) != tvg::Result::Success) return; - mask->translate(100, 250); - mask->scale(0.5f); - shape->composite(std::move(mask), tvg::CompositeMethod::AddMask); - canvas->push(std::move(shape)); - - //Shape + Image Mask Subtract - auto shape2 = tvg::Shape::gen(); - shape2->appendCircle(400, 250, 50, 50); - shape2->fill(255, 255, 255, 127); - - auto mask2 = tvg::Picture::gen(); - if (mask2->load(data, 200, 300, true) != tvg::Result::Success) return; - mask2->translate(350, 250); - mask2->scale(0.5f); - shape2->composite(std::move(mask2), tvg::CompositeMethod::SubtractMask); - - canvas->push(std::move(shape2)); - - //Shape + Image Mask Intersect - auto shape3 = tvg::Shape::gen(); - shape3->appendCircle(650, 250, 50, 50); - shape3->fill(255, 255, 255, 127); - - auto mask3 = tvg::Picture::gen(); - if (mask3->load(data, 200, 300, true) != tvg::Result::Success) return; - mask3->translate(600, 250); - mask3->scale(0.5f); - shape3->composite(std::move(mask3), tvg::CompositeMethod::IntersectMask); - - canvas->push(std::move(shape3)); - - //Shape + Image Mask Difference - auto shape4 = tvg::Shape::gen(); - shape4->appendCircle(900, 250, 50, 50); - shape4->fill(255, 255, 255); - - auto mask4 = tvg::Picture::gen(); - if (mask4->load(data, 200, 300, true) != tvg::Result::Success) return; - mask4->translate(850, 250); - mask4->scale(0.5f); - shape4->composite(std::move(mask4), tvg::CompositeMethod::DifferenceMask); - - canvas->push(std::move(shape4)); - } - - { - //Rect + Rect Mask Add - auto shape = tvg::Shape::gen(); - shape->appendRect(75, 500, 100, 100); + shape->appendCircle(125, 300, 100, 100); shape->fill(255, 255, 255); auto mask = tvg::Shape::gen(); - mask->appendRect(125, 450, 100, 100); + mask->appendCircle(125, 300, 50, 50); mask->fill(255, 255, 255); - shape->composite(std::move(mask), tvg::CompositeMethod::AddMask); + auto add = tvg::Shape::gen(); + add->appendCircle(175, 300, 50, 50); + add->fill(255, 255, 255); + mask->composite(std::move(add), tvg::CompositeMethod::AddMask); + shape->composite(std::move(mask), tvg::CompositeMethod::InvAlphaMask); + canvas->push(std::move(shape)); + + //Shape + Shape Mask Subtract + auto shape2 = tvg::Shape::gen(); + shape2->appendCircle(375, 300, 100, 100); + shape2->fill(255, 255, 255, 255); + + auto mask2 = tvg::Shape::gen(); + mask2->appendCircle(375, 300, 50, 50); + mask2->fill(255, 255, 255, 127); + + auto sub = tvg::Shape::gen(); + sub->appendCircle(400, 300, 50, 50); + sub->fill(255, 255, 255); + mask2->composite(std::move(sub), tvg::CompositeMethod::SubtractMask); + shape2->composite(std::move(mask2), tvg::CompositeMethod::InvAlphaMask); + canvas->push(std::move(shape2)); + + //Shape + Shape Mask Intersect + auto shape3 = tvg::Shape::gen(); + shape3->appendCircle(625, 300, 100, 100); + shape3->fill(255, 255, 255, 127); + + auto mask3 = tvg::Shape::gen(); + mask3->appendCircle(625, 300, 50, 50); + mask3->fill(255, 255, 255, 127); + + auto inter = tvg::Shape::gen(); + inter->appendCircle(650, 300, 50, 50); + inter->fill(255, 255, 255); + mask3->composite(std::move(inter), tvg::CompositeMethod::IntersectMask); + shape3->composite(std::move(mask3), tvg::CompositeMethod::InvAlphaMask); + canvas->push(std::move(shape3)); + + //Shape + Shape Mask Difference + auto shape4 = tvg::Shape::gen(); + shape4->appendCircle(875, 300, 100, 100); + shape4->fill(255, 255, 255); + + auto mask4 = tvg::Shape::gen(); + mask4->appendCircle(875, 300, 50, 50); + mask4->fill(255, 255, 255); + + auto diff = tvg::Shape::gen(); + diff->appendCircle(900, 300, 50, 50); + diff->fill(255, 255, 255); + mask4->composite(std::move(diff), tvg::CompositeMethod::DifferenceMask); + shape4->composite(std::move(mask4), tvg::CompositeMethod::InvAlphaMask); + canvas->push(std::move(shape4)); + } + { + //Rect + Rect Mask Add + auto shape = tvg::Shape::gen(); + shape->appendRect(75, 450, 150, 150); + shape->fill(255, 255, 255); + + auto mask = tvg::Shape::gen(); + mask->appendRect(75, 500, 100, 100); + mask->fill(255, 255, 255); + + auto add = tvg::Shape::gen(); + add->appendRect(125, 450, 100, 100); + add->fill(255, 255, 255); + mask->composite(std::move(add), tvg::CompositeMethod::AddMask); + shape->composite(std::move(mask), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(shape)); //Rect + Rect Mask Subtract auto shape2 = tvg::Shape::gen(); - shape2->appendRect(325, 500, 100, 100); - shape2->fill(255, 255, 255, 127); + shape2->appendRect(325, 450, 150, 150); + shape2->fill(255, 255, 255); auto mask2 = tvg::Shape::gen(); - mask2->appendRect(375, 450, 100, 100); - mask2->fill(255, 255, 255); - shape2->composite(std::move(mask2), tvg::CompositeMethod::SubtractMask); + mask2->appendRect(325, 500, 100, 100); + mask2->fill(255, 255, 255, 127); + auto sub = tvg::Shape::gen(); + sub->appendRect(375, 450, 100, 100); + sub->fill(255, 255, 255); + mask2->composite(std::move(sub), tvg::CompositeMethod::SubtractMask); + shape2->composite(std::move(mask2), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(shape2)); //Rect + Rect Mask Intersect auto shape3 = tvg::Shape::gen(); - shape3->appendRect(575, 500, 100, 100); - shape3->fill(255, 255, 255, 127); + shape3->appendRect(575, 450, 150, 150); + shape3->fill(255, 255, 255); auto mask3 = tvg::Shape::gen(); - mask3->appendRect(625, 450, 100, 100); - mask3->fill(255, 255, 255); - shape3->composite(std::move(mask3), tvg::CompositeMethod::IntersectMask); + mask3->appendRect(575, 500, 100, 100); + mask3->fill(255, 255, 255, 127); + auto inter = tvg::Shape::gen(); + inter->appendRect(625, 450, 100, 100); + inter->fill(255, 255, 255); + mask3->composite(std::move(inter), tvg::CompositeMethod::IntersectMask); + shape3->composite(std::move(mask3), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(shape3)); //Rect + Rect Mask Difference auto shape4 = tvg::Shape::gen(); - shape4->appendRect(825, 500, 100, 100); + shape4->appendRect(825, 450, 150, 150); shape4->fill(255, 255, 255); auto mask4 = tvg::Shape::gen(); - mask4->appendRect(875, 450, 100, 100); + mask4->appendRect(825, 500, 100, 100); mask4->fill(255, 255, 255); - shape4->composite(std::move(mask4), tvg::CompositeMethod::DifferenceMask); + auto diff = tvg::Shape::gen(); + diff->appendRect(875, 450, 100, 100); + diff->fill(255, 255, 255); + mask4->composite(std::move(diff), tvg::CompositeMethod::DifferenceMask); + shape4->composite(std::move(mask4), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(shape4)); } @@ -209,7 +251,12 @@ void tvgDrawCmds(tvg::Canvas* canvas) auto mask = tvg::Shape::gen(); mask->appendCircle(125, 700, 50, 50); mask->fill(255, 255, 255); - image->composite(std::move(mask), tvg::CompositeMethod::AddMask); + + auto add = tvg::Shape::gen(); + add->appendCircle(150, 750, 50, 50); + add->fill(255, 255, 255); + mask->composite(std::move(add), tvg::CompositeMethod::AddMask); + image->composite(std::move(mask), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(image)); //Transformed Image + Shape Mask Subtract @@ -218,12 +265,16 @@ void tvgDrawCmds(tvg::Canvas* canvas) image2->translate(400, 650); image2->scale(0.5f); image2->rotate(45); - image2->opacity(127); auto mask2 = tvg::Shape::gen(); mask2->appendCircle(375, 700, 50, 50); - mask2->fill(255, 255, 255); - image2->composite(std::move(mask2), tvg::CompositeMethod::SubtractMask); + mask2->fill(255, 255, 255, 127); + + auto sub = tvg::Shape::gen(); + sub->appendCircle(400, 750, 50, 50); + sub->fill(255, 255, 255); + mask2->composite(std::move(sub), tvg::CompositeMethod::SubtractMask); + image2->composite(std::move(mask2), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(image2)); //Transformed Image + Shape Mask Intersect @@ -232,12 +283,16 @@ void tvgDrawCmds(tvg::Canvas* canvas) image3->translate(650, 650); image3->scale(0.5f); image3->rotate(45); - image3->opacity(127); auto mask3 = tvg::Shape::gen(); mask3->appendCircle(625, 700, 50, 50); - mask3->fill(255, 255, 255); - image3->composite(std::move(mask3), tvg::CompositeMethod::IntersectMask); + mask3->fill(255, 255, 255, 127); + + auto inter = tvg::Shape::gen(); + inter->appendCircle(650, 750, 50, 50); + inter->fill(255, 255, 255, 127); + mask3->composite(std::move(inter), tvg::CompositeMethod::IntersectMask); + image3->composite(std::move(mask3), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(image3)); //Transformed Image + Shape Mask Difference @@ -250,91 +305,87 @@ void tvgDrawCmds(tvg::Canvas* canvas) auto mask4 = tvg::Shape::gen(); mask4->appendCircle(875, 700, 50, 50); mask4->fill(255, 255, 255); - image4->composite(std::move(mask4), tvg::CompositeMethod::DifferenceMask); + + auto diff = tvg::Shape::gen(); + diff->appendCircle(900, 750, 50, 50); + diff->fill(255, 255, 255); + mask4->composite(std::move(diff), tvg::CompositeMethod::DifferenceMask); + image4->composite(std::move(mask4), tvg::CompositeMethod::AlphaMask); canvas->push(std::move(image4)); } - { - //Gradient Color Stops - tvg::Fill::ColorStop colorStops[2]; - colorStops[0] = {0, 255, 0, 0, 255}; - colorStops[1] = {1, 255, 255, 255, 255}; - - //Shape + Shape Mask Add - auto shape = tvg::Shape::gen(); - shape->appendRect(75, 850, 100, 100, 10, 10); - - //LinearGradient - auto fill = tvg::LinearGradient::gen(); - fill->linear(75, 850, 175, 950); - fill->colorStops(colorStops, 2); - shape->fill(std::move(fill)); + //Transformed Image + Shape Mask Add + auto image = tvg::Picture::gen(); + if (image->load(data, 200, 300, true) != tvg::Result::Success) return; + image->translate(150, 850); + image->scale(0.5f); + image->rotate(45); auto mask = tvg::Shape::gen(); - mask->appendCircle(175, 900, 50, 50); + mask->appendCircle(125, 900, 50, 50); mask->fill(255, 255, 255); - shape->composite(std::move(mask), tvg::CompositeMethod::AddMask); - canvas->push(std::move(shape)); + auto add = tvg::Shape::gen(); + add->appendCircle(150, 950, 50, 50); + add->fill(255, 255, 255); + mask->composite(std::move(add), tvg::CompositeMethod::AddMask); + image->composite(std::move(mask), tvg::CompositeMethod::InvAlphaMask); + canvas->push(std::move(image)); - //Shape + Shape Mask Subtract - auto shape2 = tvg::Shape::gen(); - shape2->appendRect(300, 850, 100, 100, 10, 10); - - //LinearGradient - auto fill2 = tvg::LinearGradient::gen(); - fill2->linear(300, 850, 400, 950); - fill2->colorStops(colorStops, 2); - shape2->fill(std::move(fill2)); - shape2->opacity(127); + //Transformed Image + Shape Mask Subtract + auto image2 = tvg::Picture::gen(); + if (image2->load(data, 200, 300, true) != tvg::Result::Success) return; + image2->translate(400, 850); + image2->scale(0.5f); + image2->rotate(45); auto mask2 = tvg::Shape::gen(); - mask2->appendCircle(400, 900, 50, 50); - mask2->fill(255, 255, 255); + mask2->appendCircle(375, 900, 50, 50); + mask2->fill(255, 255, 255, 127); - shape2->composite(std::move(mask2), tvg::CompositeMethod::SubtractMask); + auto sub = tvg::Shape::gen(); + sub->appendCircle(400, 950, 50, 50); + sub->fill(255, 255, 255); + mask2->composite(std::move(sub), tvg::CompositeMethod::SubtractMask); + image2->composite(std::move(mask2), tvg::CompositeMethod::InvAlphaMask); + canvas->push(std::move(image2)); - canvas->push(std::move(shape2)); - - //Shape + Shape Mask Intersect - auto shape3 = tvg::Shape::gen(); - shape3->appendRect(550, 850, 100, 100, 10, 10); - - //LinearGradient - auto fill3 = tvg::LinearGradient::gen(); - fill3->linear(550, 850, 650, 950); - fill3->colorStops(colorStops, 2); - shape3->fill(std::move(fill3)); - shape3->opacity(127); + //Transformed Image + Shape Mask Intersect + auto image3 = tvg::Picture::gen(); + if (image3->load(data, 200, 300, true) != tvg::Result::Success) return; + image3->translate(650, 850); + image3->scale(0.5f); + image3->rotate(45); auto mask3 = tvg::Shape::gen(); - mask3->appendCircle(650, 900, 50, 50); - mask3->fill(255, 255, 255); - shape3->composite(std::move(mask3), tvg::CompositeMethod::IntersectMask); + mask3->appendCircle(625, 900, 50, 50); + mask3->fill(255, 255, 255, 127); - canvas->push(std::move(shape3)); - - //Shape + Shape Mask Difference - auto shape4 = tvg::Shape::gen(); - shape4->appendRect(800, 850, 100, 100, 10, 10); - shape4->fill(255, 255, 255); - - //LinearGradient - auto fill4 = tvg::LinearGradient::gen(); - fill4->linear(800, 850, 900, 950); - fill4->colorStops(colorStops, 2); - shape4->fill(std::move(fill4)); + auto inter = tvg::Shape::gen(); + inter->appendCircle(650, 950, 50, 50); + inter->fill(255, 255, 255, 127); + mask3->composite(std::move(inter), tvg::CompositeMethod::IntersectMask); + image3->composite(std::move(mask3), tvg::CompositeMethod::InvAlphaMask); + canvas->push(std::move(image3)); + //Transformed Image + Shape Mask Difference + auto image4 = tvg::Picture::gen(); + if (image4->load(data, 200, 300, true) != tvg::Result::Success) return; + image4->translate(900, 850); + image4->scale(0.5f); + image4->rotate(45); auto mask4 = tvg::Shape::gen(); - mask4->appendCircle(900, 900, 50, 50); + mask4->appendCircle(875, 900, 50, 50); mask4->fill(255, 255, 255); - shape4->composite(std::move(mask4), tvg::CompositeMethod::DifferenceMask); - canvas->push(std::move(shape4)); + auto diff = tvg::Shape::gen(); + diff->appendCircle(900, 950, 50, 50); + diff->fill(255, 255, 255); + mask4->composite(std::move(diff), tvg::CompositeMethod::DifferenceMask); + image4->composite(std::move(mask4), tvg::CompositeMethod::InvAlphaMask); + canvas->push(std::move(image4)); } - - free(data); } diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index ecf3f7e6..d99bddd9 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -235,6 +235,7 @@ struct SwImage bool scaled = false; //draw scaled image }; +typedef uint8_t(*SwMask)(uint8_t s, uint8_t d, uint8_t a); //src, dst, alpha typedef uint32_t(*SwBlender)(uint32_t s, uint32_t d, uint8_t a); //src, dst, alpha typedef uint32_t(*SwJoin)(uint8_t r, uint8_t g, uint8_t b, uint8_t a); //color channel join typedef uint8_t(*SwAlpha)(uint8_t*); //blending alpha @@ -295,7 +296,7 @@ static inline uint32_t INTERPOLATE(uint32_t s, uint32_t d, uint8_t a) static inline uint8_t INTERPOLATE8(uint8_t s, uint8_t d, uint8_t a) { - return ((s * a + 0xff) >> 8) + ((d * ~a + 0xff) >> 8); + return (((s) * (a) + 0xff) >> 8) + (((d) * ~(a) + 0xff) >> 8); } static inline SwCoord HALF_STROKE(float width) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 36ba09f3..dba666ae 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -85,9 +85,6 @@ struct FillRadial }; -static bool _rasterDirectImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity = 255); - - static inline uint8_t _alpha(uint8_t* a) { return *a; @@ -166,52 +163,54 @@ static inline bool _masking(const SwSurface* surface) } -static inline uint32_t _opMaskAdd(uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opMaskAdd(uint8_t s, uint8_t d, uint8_t a) { - return s + ALPHA_BLEND(d, a); + return s + MULTIPLY(d, a); } -static inline uint32_t _opMaskSubtract(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +static inline uint8_t _opMaskSubtract(uint8_t s, uint8_t d, TVG_UNUSED uint8_t a) { - return ALPHA_BLEND(s, IA(d)); + return MULTIPLY(s, 255 - d); } -static inline uint32_t _opMaskIntersect(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +static inline uint8_t _opMaskIntersect(uint8_t s, uint8_t d, TVG_UNUSED uint8_t a) { - return ALPHA_BLEND(s, A(d)); + return MULTIPLY(s, d); } -static inline uint32_t _opMaskDifference(uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opMaskDifference(uint8_t s, uint8_t d, uint8_t a) { - return ALPHA_BLEND(s, IA(d)) + ALPHA_BLEND(d, a); + return MULTIPLY(s, 255 - d) + MULTIPLY(d, a); } -static inline uint32_t _opAMaskAdd(uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opAMaskAdd(uint8_t s, uint8_t d, uint8_t a) { - return INTERPOLATE(s, d, a); + return INTERPOLATE8(s, d, a); } -static inline uint32_t _opAMaskSubtract(TVG_UNUSED uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opAMaskSubtract(TVG_UNUSED uint8_t s, uint8_t d, uint8_t a) { - return ALPHA_BLEND(s, MULTIPLY(IA(d), a)); + return s; + //return ALPHA_BLEND(s, MULTIPLY(IA(d), a)); } -static inline uint32_t _opAMaskDifference(uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opAMaskDifference(uint8_t s, uint8_t d, uint8_t a) { - auto t = ALPHA_BLEND(s, a); - return ALPHA_BLEND(t, IA(d)) + ALPHA_BLEND(d, IA(t)); + auto t = MULTIPLY(s, a); + return MULTIPLY(t, 255 - d) + MULTIPLY(d, 255 - t); } -static inline uint32_t _opAMaskIntersect(uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opAMaskIntersect(uint8_t s, uint8_t d, uint8_t a) { - return ALPHA_BLEND(s, MULTIPLY(A(d), a)); + return s; + //return ALPHA_BLEND(s, MULTIPLY(A(d), a)); } @@ -223,7 +222,7 @@ static inline bool _direct(CompositeMethod method) } -static inline SwBlender _getMaskOp(CompositeMethod method) +static inline SwMask _getMaskOp(CompositeMethod method) { switch (method) { case CompositeMethod::AddMask: return _opMaskAdd; @@ -235,7 +234,7 @@ static inline SwBlender _getMaskOp(CompositeMethod method) } -static inline SwBlender _getAMaskOp(CompositeMethod method) +static inline SwMask _getAMaskOp(CompositeMethod method) { switch (method) { case CompositeMethod::AddMask: return _opAMaskAdd; @@ -247,6 +246,24 @@ static inline SwBlender _getAMaskOp(CompositeMethod method) } +static bool _compositeMaskImage(SwSurface* surface, const SwImage* image, const SwBBox& region) +{ + auto dbuffer = &surface->buf8[region.min.y * surface->stride + region.min.x]; + auto sbuffer = image->buf8 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + + for (auto y = region.min.y; y < region.max.y; ++y) { + auto dst = dbuffer; + auto src = sbuffer; + for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) { + *dst = *src + MULTIPLY(*dst, ~*src); + } + dbuffer += surface->stride; + sbuffer += image->stride; + } + return true; +} + + #include "tvgSwRasterTexmap.h" #include "tvgSwRasterC.h" #include "tvgSwRasterAvx.h" @@ -316,40 +333,38 @@ static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t /* Rect */ /************************************************************************/ -static bool _rasterCompositeMaskedRect(SwSurface* surface, const SwBBox& region, SwBlender maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static bool _rasterCompositeMaskedRect(SwSurface* surface, const SwBBox& region, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { auto w = static_cast(region.max.x - region.min.x); auto h = static_cast(region.max.y - region.min.y); - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride + region.min.x); //compositor buffer auto cstride = surface->compositor->image.stride; - auto color = surface->join(r, g, b, a); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); //compositor buffer auto ialpha = 255 - a; for (uint32_t y = 0; y < h; ++y) { auto cmp = cbuffer; for (uint32_t x = 0; x < w; ++x, ++cmp) { - *cmp = maskOp(color, *cmp, ialpha); + *cmp = maskOp(a, *cmp, ialpha); } cbuffer += cstride; } - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static bool _rasterDirectMaskedRect(SwSurface* surface, const SwBBox& region, SwBlender maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static bool _rasterDirectMaskedRect(SwSurface* surface, const SwBBox& region, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { auto w = static_cast(region.max.x - region.min.x); auto h = static_cast(region.max.y - region.min.y); - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride + region.min.x); //compositor buffer - auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); //destination buffer - auto color = surface->join(r, g, b, a); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x); //compositor buffer + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); //destination buffer for (uint32_t y = 0; y < h; ++y) { auto cmp = cbuffer; auto dst = dbuffer; for (uint32_t x = 0; x < w; ++x, ++cmp, ++dst) { - auto tmp = maskOp(color, *cmp, 0); //not use alpha. - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + auto tmp = maskOp(a, *cmp, 0); //not use alpha. + *dst = tmp + MULTIPLY(*dst, ~tmp); } cbuffer += surface->compositor->image.stride; dbuffer += surface->stride; @@ -360,13 +375,12 @@ static bool _rasterDirectMaskedRect(SwSurface* surface, const SwBBox& region, Sw static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - //32bit channels composition - if (surface->channelSize != sizeof(uint32_t)) return false; + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; TVGLOG("SW_ENGINE", "Masked(%d) Rect [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); auto maskOp = _getMaskOp(surface->compositor->method); - if (_direct(surface->compositor->method)) return _rasterDirectMaskedRect(surface, region, maskOp, r, g, b, a); else return _rasterCompositeMaskedRect(surface, region, maskOp, r, g, b, a); return false; @@ -458,7 +472,7 @@ static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint8_t r //8bits grayscale if (surface->channelSize == sizeof(uint8_t)) { for (uint32_t y = 0; y < h; ++y) { - rasterGrayscale8(surface->buf8, 255, region.min.y * surface->stride + region.min.x, w); + rasterGrayscale8(surface->buf8, 255, (y + region.min.y) * surface->stride + region.min.x, w); } return true; } @@ -485,43 +499,41 @@ static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint8_t r, uin /* Rle */ /************************************************************************/ -static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRleData* rle, SwBlender maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRleData* rle, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { auto span = rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; auto cstride = surface->compositor->image.stride; - auto color = surface->join(r, g, b, a); - uint32_t src; + uint8_t src; for (uint32_t i = 0; i < rle->size; ++i, ++span) { auto cmp = &cbuffer[span->y * cstride + span->x]; - if (span->coverage == 255) src = color; - else src = ALPHA_BLEND(color, span->coverage); - auto ialpha = IA(src); + if (span->coverage == 255) src = a; + else src = MULTIPLY(a, span->coverage); + auto ialpha = 255 - src; for (auto x = 0; x < span->len; ++x, ++cmp) { *cmp = maskOp(src, *cmp, ialpha); } } - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static bool _rasterDirectMaskedRle(SwSurface* surface, SwRleData* rle, SwBlender maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static bool _rasterDirectMaskedRle(SwSurface* surface, SwRleData* rle, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { auto span = rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; auto cstride = surface->compositor->image.stride; - auto color = surface->join(r, g, b, a); - uint32_t src; + uint8_t src; for (uint32_t i = 0; i < rle->size; ++i, ++span) { auto cmp = &cbuffer[span->y * cstride + span->x]; - auto dst = &surface->buf32[span->y * surface->stride + span->x]; - if (span->coverage == 255) src = color; - else src = ALPHA_BLEND(color, span->coverage); + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + if (span->coverage == 255) src = a; + else src = MULTIPLY(a, span->coverage); for (auto x = 0; x < span->len; ++x, ++cmp, ++dst) { - auto tmp = maskOp(src, *cmp, 0); //not use alpha - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + auto tmp = maskOp(src, *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); } } return true; @@ -532,11 +544,10 @@ static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint { TVGLOG("SW_ENGINE", "Masked(%d) Rle", (int)surface->compositor->method); - //32bit channels composition - if (surface->channelSize != sizeof(uint32_t)) return false; + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; auto maskOp = _getMaskOp(surface->compositor->method); - if (_direct(surface->compositor->method)) return _rasterDirectMaskedRle(surface, rle, maskOp, r, g, b, a); else return _rasterCompositeMaskedRle(surface, rle, maskOp, r, g, b, a); return false; @@ -673,7 +684,8 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, /* RLE Scaled Image */ /************************************************************************/ -static bool _rasterCompositeScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); @@ -683,21 +695,22 @@ static bool _rasterCompositeScaledMaskedRleImage(SwSurface* surface, const SwIma for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { auto sy = span->y * itransform->e22 + itransform->e23; if ((uint32_t)sy >= image->h) continue; - auto cmp = &surface->compositor->image.buf32[span->y * surface->compositor->image.stride + span->x]; + auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x]; auto a = MULTIPLY(span->coverage, opacity); if (a == 255) { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++cmp) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = maskOp(src, *cmp, 255); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + *cmp = maskOp(src, *cmp, ~src); } } else { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++cmp) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = amaskOp(src, *cmp, a); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = MULTIPLY(src, a); + *cmp = maskOp(tmp, *cmp, ~tmp); } } } @@ -705,7 +718,7 @@ static bool _rasterCompositeScaledMaskedRleImage(SwSurface* surface, const SwIma } -static bool _rasterDirectScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +static bool _rasterDirectScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); @@ -715,40 +728,43 @@ static bool _rasterDirectScaledMaskedRleImage(SwSurface* surface, const SwImage* for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { auto sy = span->y * itransform->e22 + itransform->e23; if ((uint32_t)sy >= image->h) continue; - auto cmp = &surface->compositor->image.buf32[span->y * surface->compositor->image.stride + span->x]; - auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x]; + auto dst = &surface->buf8[span->y * surface->stride + span->x]; auto a = MULTIPLY(span->coverage, opacity); if (a == 255) { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++cmp, ++dst) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); auto tmp = maskOp(src, *cmp, 0); //not use alpha - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + *dst = tmp + MULTIPLY(*dst, ~tmp); } } else { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++cmp, ++dst) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = amaskOp(src, *cmp, a); - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = maskOp(MULTIPLY(src, a), *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); } } } - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } - +#endif static bool _rasterScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { +#if 0 //Enable it when GRAYSCALE image is supported TVGLOG("SW_ENGINE", "Scaled Masked(%d) Rle Image", (int)surface->compositor->method); - auto maskOp = _getMaskOp(surface->compositor->method); - auto amaskOp = _getAMaskOp(surface->compositor->method); + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; - if (_direct(surface->compositor->method)) return _rasterDirectScaledMaskedRleImage(surface, image, itransform, region, maskOp, amaskOp, opacity); - else return _rasterCompositeScaledMaskedRleImage(surface, image, itransform, region, maskOp, amaskOp, opacity); + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectScaledMaskedRleImage(surface, image, itransform, region, maskOp, opacity); + else return _rasterCompositeScaledMaskedRleImage(surface, image, itransform, region, maskOp, opacity); +#endif return false; } @@ -891,66 +907,71 @@ static bool _scaledRleImage(SwSurface* surface, const SwImage* image, const Matr /* RLE Direct Image */ /************************************************************************/ -static bool _rasterCompositeDirectMaskedRleImage(SwSurface* surface, const SwImage* image, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeDirectMaskedRleImage(SwSurface* surface, const SwImage* image, SwMask maskOp, uint8_t opacity) { auto span = image->rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; auto ctride = surface->compositor->image.stride; for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto src = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto src = image->buf8 + (span->y + image->oy) * image->stride + (span->x + image->ox); auto cmp = &cbuffer[span->y * ctride + span->x]; auto alpha = MULTIPLY(span->coverage, opacity); if (alpha == 255) { for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp) { - *cmp = maskOp(*src, *cmp, IA(*src)); + *cmp = maskOp(*src, *cmp, ~*src); } } else { for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp) { - *cmp = amaskOp(*src, *cmp, alpha); + auto tmp = MULTIPLY(*src, alpha); + *cmp = maskOp(*src, *cmp, ~tmp); } } } - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static bool _rasterDirectDirectMaskedRleImage(SwSurface* surface, const SwImage* image, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +static bool _rasterDirectDirectMaskedRleImage(SwSurface* surface, const SwImage* image, SwMask maskOp, uint8_t opacity) { auto span = image->rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; auto ctride = surface->compositor->image.stride; for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto src = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto src = image->buf8 + (span->y + image->oy) * image->stride + (span->x + image->ox); auto cmp = &cbuffer[span->y * ctride + span->x]; - auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto dst = &surface->buf8[span->y * surface->stride + span->x]; auto alpha = MULTIPLY(span->coverage, opacity); if (alpha == 255) { for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp, ++dst) { auto tmp = maskOp(*src, *cmp, 0); //not use alpha - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + *dst = INTERPOLATE8(tmp, *dst, (255 - tmp)); } } else { for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp, ++dst) { - auto tmp = amaskOp(*src, *cmp, alpha); - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + auto tmp = maskOp(MULTIPLY(*src, alpha), *cmp, 0); //not use alpha + *dst = INTERPOLATE8(tmp, *dst, (255 - tmp)); } } } return true; } - +#endif static bool _rasterDirectMaskedRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) { +#if 0 //Enable it when GRAYSCALE image is supported TVGLOG("SW_ENGINE", "Direct Masked(%d) Rle Image", (int)surface->compositor->method); - auto maskOp = _getMaskOp(surface->compositor->method); - auto amaskOp = _getAMaskOp(surface->compositor->method); + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; - if (_direct(surface->compositor->method)) _rasterDirectDirectMaskedRleImage(surface, image, maskOp, amaskOp, opacity); - else return _rasterCompositeDirectMaskedRleImage(surface, image, maskOp, amaskOp, opacity); + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) _rasterDirectDirectMaskedRleImage(surface, image, maskOp, opacity); + else return _rasterCompositeDirectMaskedRleImage(surface, image, maskOp, opacity); +#endif return false; } @@ -1055,13 +1076,14 @@ static bool _directRleImage(SwSurface* surface, const SwImage* image, uint8_t op /*Scaled Image */ /************************************************************************/ -static bool _rasterCompositeScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); auto sampleSize2 = sampleSize * sampleSize; auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); for (auto y = region.min.y; y < region.max.y; ++y) { auto sy = y * itransform->e22 + itransform->e23; @@ -1071,31 +1093,32 @@ static bool _rasterCompositeScaledMaskedImage(SwSurface* surface, const SwImage* for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = maskOp(src, *cmp, IA(src)); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + *cmp = maskOp(src, *cmp, ~src); } } else { for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = amaskOp(src, *cmp, opacity); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = MULTIPLY(src, opacity); + *cmp = maskOp(tmp, *cmp, ~tmp); } } cbuffer += cstride; } - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static bool _rasterDirectScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +static bool _rasterDirectScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); auto sampleSize2 = sampleSize * sampleSize; auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); - auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); for (auto y = region.min.y; y < region.max.y; ++y) { auto sy = y * itransform->e22 + itransform->e23; @@ -1106,17 +1129,18 @@ static bool _rasterDirectScaledMaskedImage(SwSurface* surface, const SwImage* im for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); auto tmp = maskOp(src, *cmp, 0); //not use alpha - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + *dst = tmp + MULTIPLY(*dst, ~tmp); } } else { for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = amaskOp(src, *cmp, opacity); - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = MULTIPLY(src, opacity); + auto tmp2 = maskOp(tmp, *cmp, 0); //not use alpha + *dst = tmp2 + MULTIPLY(*dst, ~tmp2); } } cbuffer += cstride; @@ -1124,17 +1148,17 @@ static bool _rasterDirectScaledMaskedImage(SwSurface* surface, const SwImage* im } return true; } - +#endif static bool _rasterScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { +#if 0 //Enable it when GRAYSCALE image is supported TVGLOG("SW_ENGINE", "Scaled Masked(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); auto maskOp = _getMaskOp(surface->compositor->method); - auto amaskOp = _getAMaskOp(surface->compositor->method); - - if (_direct(surface->compositor->method)) return _rasterDirectScaledMaskedImage(surface, image, itransform, region, maskOp, amaskOp, opacity); - else return _rasterCompositeScaledMaskedImage(surface, image, itransform, region, maskOp, amaskOp, opacity); + if (_direct(surface->compositor->method)) return _rasterDirectScaledMaskedImage(surface, image, itransform, region, maskOp, opacity); + else return _rasterCompositeScaledMaskedImage(surface, image, itransform, region, maskOp, opacity); +#endif return false; } @@ -1269,43 +1293,45 @@ static bool _scaledImage(SwSurface* surface, const SwImage* image, const Matrix* /* Direct Image */ /************************************************************************/ -static bool _rasterCompositeDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); //compositor buffer - auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); //compositor buffer + auto sbuffer = image->buf8 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); for (uint32_t y = 0; y < h; ++y) { auto cmp = cbuffer; auto src = sbuffer; if (opacity == 255) { for (uint32_t x = 0; x < w; ++x, ++src, ++cmp) { - *cmp = maskOp(*src, *cmp, IA(*src)); + *cmp = maskOp(*src, *cmp, ~*src); } } else { for (uint32_t x = 0; x < w; ++x, ++src, ++cmp) { - *cmp = amaskOp(*src, *cmp, opacity); + auto tmp = MULTIPLY(*src, opacity); + *cmp = maskOp(tmp, *cmp, ~tmp); } } cbuffer += cstride; sbuffer += image->stride; } - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static bool _rasterDirectDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +static bool _rasterDirectDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); auto cstride = surface->compositor->image.stride; auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); //compositor buffer - auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); //destination buffer - auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); //destination buffer + auto sbuffer = image->buf8 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); for (uint32_t y = 0; y < h; ++y) { auto cmp = cbuffer; @@ -1314,12 +1340,12 @@ static bool _rasterDirectDirectMaskedImage(SwSurface* surface, const SwImage* im if (opacity == 255) { for (uint32_t x = 0; x < w; ++x, ++src, ++cmp, ++dst) { auto tmp = maskOp(*src, *cmp, 0); //not use alpha - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + *dst = tmp + MULTIPLY(*dst, ~tmp); } } else { for (uint32_t x = 0; x < w; ++x, ++src, ++cmp, ++dst) { - auto tmp = amaskOp(*src, *cmp, opacity); - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + auto tmp = maskOp(MULTIPLY(*src, opacity), *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); } } cbuffer += cstride; @@ -1328,17 +1354,17 @@ static bool _rasterDirectDirectMaskedImage(SwSurface* surface, const SwImage* im } return true; } - +#endif static bool _rasterDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) { +#if 0 //Enable it when GRAYSCALE image is supported TVGLOG("SW_ENGINE", "Direct Masked(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); auto maskOp = _getMaskOp(surface->compositor->method); - auto amaskOp = _getAMaskOp(surface->compositor->method); - - if (_direct(surface->compositor->method)) return _rasterDirectDirectMaskedImage(surface, image, region, maskOp, amaskOp, opacity); - else return _rasterCompositeDirectMaskedImage(surface, image, region, maskOp, amaskOp, opacity); + if (_direct(surface->compositor->method)) return _rasterDirectDirectMaskedImage(surface, image, region, maskOp, opacity); + else return _rasterCompositeDirectMaskedImage(surface, image, region, maskOp, opacity); +#endif return false; } @@ -1466,20 +1492,20 @@ static bool _rasterImage(SwSurface* surface, SwImage* image, const Matrix* trans /************************************************************************/ /* Rect Gradient */ /************************************************************************/ - +#if 0 template static bool _rasterCompositeGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwBlender maskOp) { auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); for (uint32_t y = 0; y < h; ++y) { fillMethod()(fill, cbuffer, region.min.y + y, region.min.x, w, maskOp, 255); cbuffer += surface->stride; } - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox, 255); + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } @@ -1499,19 +1525,21 @@ static bool _rasterDirectGradientMaskedRect(SwSurface* surface, const SwBBox& re } return true; } - +#endif template static bool _rasterGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) { +#if 0 auto method = surface->compositor->method; TVGLOG("SW_ENGINE", "Masked(%d) Gradient [Region: %lu %lu %lu %lu]", (int)method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); - auto amaskOp = _getAMaskOp(method); + auto maskOp = _getMaskOp(method); - if (_direct(method)) return _rasterDirectGradientMaskedRect(surface, region, fill, amaskOp); - else return _rasterCompositeGradientMaskedRect(surface, region, fill, amaskOp); + if (_direct(method)) return _rasterDirectGradientMaskedRect(surface, region, fill, maskOp); + else return _rasterCompositeGradientMaskedRect(surface, region, fill, maskOp); +#endif return false; } @@ -1623,7 +1651,7 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, /************************************************************************/ /* Rle Gradient */ /************************************************************************/ - +#if 0 template static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwBlender maskOp) { @@ -1654,7 +1682,7 @@ static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRleData* } return true; } - +#endif template static bool _rasterGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) @@ -1665,8 +1693,8 @@ static bool _rasterGradientMaskedRle(SwSurface* surface, const SwRleData* rle, c auto amaskOp = _getAMaskOp(method); - if (_direct(method)) return _rasterDirectGradientMaskedRle(surface, rle, fill, amaskOp); - else return _rasterCompositeGradientMaskedRle(surface, rle, fill, amaskOp); + //if (_direct(method)) return _rasterDirectGradientMaskedRle(surface, rle, fill, amaskOp); + //else return _rasterCompositeGradientMaskedRle(surface, rle, fill, amaskOp); return false; } diff --git a/src/lib/sw_engine/tvgSwRasterTexmap.h b/src/lib/sw_engine/tvgSwRasterTexmap.h index 938a2a39..09b0ae5d 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmap.h +++ b/src/lib/sw_engine/tvgSwRasterTexmap.h @@ -72,13 +72,15 @@ static bool _arrange(const SwImage* image, const SwBBox* region, int& yStart, in static bool _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity, uint8_t dirFlag = 0) { + return false; + +#if 0 //Enable it when GRAYSCALE image is supported auto maskOp = _getMaskOp(surface->compositor->method); - auto amaskOp = _getAMaskOp(surface->compositor->method); auto direct = _direct(surface->compositor->method); float _dudx = dudx, _dvdx = dvdx; float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya; float _xa = xa, _xb = xb, _ua = ua, _va = va; - auto sbuf = image->buf32; + auto sbuf = image->buf8; int32_t sw = static_cast(image->stride); int32_t sh = image->h; int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; @@ -138,8 +140,8 @@ static bool _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* x = x1; - auto cmp = &surface->compositor->image.buf32[y * surface->compositor->image.stride + x1]; - auto dst = &surface->buf32[y * surface->stride + x1]; + auto cmp = &surface->compositor->image.buf8[y * surface->compositor->image.stride + x1]; + auto dst = &surface->buf8[y * surface->stride + x1]; if (opacity == 255) { //Draw horizontal line @@ -177,10 +179,10 @@ static bool _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* } if (direct) { auto tmp = maskOp(px, *cmp, 0); //not use alpha - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + *dst = tmp + MULTIPLY(*dst, ~tmp); ++dst; } else { - *cmp = maskOp(px, *cmp, IA(px)); + *cmp = maskOp(px, *cmp, ~px); } ++cmp; @@ -226,11 +228,12 @@ static bool _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* } if (direct) { - auto tmp = amaskOp(px, *cmp, opacity); - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + auto tmp = maskOp(MULTIPLY(px, opacity), *cmp, 0); + *dst = tmp + MULTIPLY(*dst, ~tmp); ++dst; } else { - *cmp = amaskOp(px, *cmp, opacity); + auto tmp = MULTIPLY(px, opacity); + *cmp = maskOp(tmp, *cmp, ~px); } ++cmp; @@ -259,6 +262,7 @@ static bool _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* va = _va; return true; +#endif } @@ -1124,9 +1128,11 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const _rasterPolygonImage(surface, image, region, polygon, aaSpans, opacity); +#if 0 if (_compositing(surface) && _masking(surface) && !_direct(surface->compositor->method)) { - _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } +#endif return _apply(surface, aaSpans); } @@ -1179,9 +1185,11 @@ static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, c for (uint32_t i = 0; i < mesh->triangleCnt; i++) { _rasterPolygonImage(surface, image, region, transformedTris[i], aaSpans, opacity); } +#if 0 if (_compositing(surface) && _masking(surface) && !_direct(surface->compositor->method)) { - _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } +#endif _apply(surface, aaSpans); } free(transformedTris); diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 0e32e380..0742a197 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -297,13 +297,14 @@ static inline ColorSpace COMPOSITE_TO_COLORSPACE(RenderMethod& renderer, Composi switch(method) { case CompositeMethod::AlphaMask: case CompositeMethod::InvAlphaMask: - return ColorSpace::Grayscale8; - case CompositeMethod::LumaMask: - case CompositeMethod::InvLumaMask: case CompositeMethod::AddMask: + case CompositeMethod::DifferenceMask: case CompositeMethod::SubtractMask: case CompositeMethod::IntersectMask: - case CompositeMethod::DifferenceMask: + return ColorSpace::Grayscale8; + //TODO: Optimize Luma/InvLuma colorspace to Grayscale8 + case CompositeMethod::LumaMask: + case CompositeMethod::InvLumaMask: return renderer.colorSpace(); default: TVGERR("RENDERER", "Unsupported Composite Size! = %d", (int)method);