common sw_engine: apply partial composition.
authorHermet Park <hermetpark@gmail.com>
Mon, 14 Dec 2020 03:29:37 +0000 (12:29 +0900)
committerJunsuChoi <jsuya.choi@samsung.com>
Tue, 15 Dec 2020 02:03:33 +0000 (11:03 +0900)
Introduce RendererMethod::renderRegion() to return acutal drawing region info.

That is used by scene composition to composite actual partial drawing region

for better performance.

@Issues: 173

Change-Id: I5b3bb6cc37c1bc25c6f9f284f13e60da811d267b

13 files changed:
src/lib/gl_engine/tvgGlRenderer.cpp
src/lib/gl_engine/tvgGlRenderer.h
src/lib/sw_engine/tvgSwCommon.h
src/lib/sw_engine/tvgSwImage.cpp
src/lib/sw_engine/tvgSwRaster.cpp
src/lib/sw_engine/tvgSwRenderer.cpp
src/lib/sw_engine/tvgSwRenderer.h
src/lib/sw_engine/tvgSwShape.cpp
src/lib/tvgPaint.h
src/lib/tvgPictureImpl.h
src/lib/tvgRender.h
src/lib/tvgSceneImpl.h
src/lib/tvgShapeImpl.h

index d94da50..1a4cbed 100644 (file)
@@ -73,6 +73,12 @@ bool GlRenderer::sync()
 }
 
 
+bool GlRenderer::renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
+{
+    return true;
+}
+
+
 bool GlRenderer::preRender()
 {
     if (mRenderTasks.size() == 0)
index 9dd9694..d7cb96c 100644 (file)
@@ -39,6 +39,7 @@ public:
     bool render(const Shape& shape, void *data) override;
     bool render(const Picture& picture, void *data) override;
     bool postRender() override;
+    bool renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
     bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
     bool sync() override;
     bool clear() override;
index 6f26e8c..3b14f5e 100644 (file)
@@ -207,7 +207,7 @@ struct SwShape
     SwFill*      fill = nullptr;
     SwRleData*   rle = nullptr;
     SwRleData*   strokeRle = nullptr;
-    SwBBox       bbox;
+    SwBBox       bbox;   //keep it boundary without stroke region. Using for optimal filling.
 
     bool         rect;   //Fast Track: Othogonal rectangle?
 };
@@ -217,7 +217,6 @@ struct SwImage
     SwOutline*   outline = nullptr;
     SwRleData*   rle = nullptr;
     uint32_t*    data = nullptr;
-    SwBBox       bbox;
     uint32_t     w, h;
 };
 
@@ -277,12 +276,12 @@ SwPoint mathTransform(const Point* to, const Matrix* transform);
 
 void shapeReset(SwShape* shape);
 bool shapeGenOutline(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform);
-bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform);
+bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox);
 bool shapePrepared(SwShape* shape);
 bool shapeGenRle(SwShape* shape, const Shape* sdata, const SwSize& clip, bool antiAlias, bool hasComposite);
 void shapeDelOutline(SwShape* shape, uint32_t tid);
 void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform);
-bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip);
+bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip, SwBBox& bbox);
 void shapeFree(SwShape* shape);
 void shapeDelStroke(SwShape* shape);
 bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, bool ctable);
@@ -294,9 +293,9 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
 SwOutline* strokeExportOutline(SwStroke* stroke, unsigned tid);
 void strokeFree(SwStroke* stroke);
 
-bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform);
+bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox);
 bool imagePrepared(SwImage* image);
-bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, bool antiAlias, bool hasComposite);
+bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, SwBBox& bbox, bool antiAlias, bool hasComposite);
 void imageDelOutline(SwImage* image, uint32_t tid);
 void imageReset(SwImage* image);
 bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform);
@@ -325,7 +324,7 @@ void mpoolRetStrokeOutline(unsigned idx);
 bool rasterCompositor(SwSurface* surface);
 bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
 bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
-bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, uint8_t opacity);
+bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, SwBBox& bbox, uint8_t opacity);
 bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
 bool rasterClear(SwSurface* surface);
 
index cefcc07..2968cb1 100644 (file)
@@ -90,13 +90,13 @@ static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSi
 /************************************************************************/
 
 
-bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform)
+bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox)
 {
     if (!imageGenOutline(image, pdata, tid, transform)) return false;
 
-    if (!_updateBBox(image->outline, image->bbox, clip))  return false;
+    if (!_updateBBox(image->outline, bbox, clip))  return false;
 
-    if (!_checkValid(image->outline, image->bbox, clip)) return false;
+    if (!_checkValid(image->outline, bbox, clip)) return false;
 
     return true;
 }
@@ -108,9 +108,9 @@ bool imagePrepared(SwImage* image)
 }
 
 
-bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, bool antiAlias, bool hasComposite)
+bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, SwBBox& bbox, bool antiAlias, bool hasComposite)
 {
-    if ((image->rle = rleRender(image->rle, image->outline, image->bbox, clip, antiAlias))) return true;
+    if ((image->rle = rleRender(image->rle, image->outline, bbox, clip, antiAlias))) return true;
 
     return false;
 }
@@ -127,7 +127,6 @@ void imageReset(SwImage* image)
 {
     rleReset(image->rle);
     image->rle = nullptr;
-    _initBBox(image->bbox);
 }
 
 
index 577b577..5518c49 100644 (file)
@@ -498,7 +498,7 @@ bool rasterClear(SwSurface* surface)
 }
 
 
-bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, uint8_t opacity)
+bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, SwBBox& bbox, uint8_t opacity)
 {
     Matrix invTransform;
 
@@ -512,11 +512,11 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, ui
     else {
         // Fast track
         if (_identify(transform)) {
-            return _rasterImage(surface, image->data, image->w, image->h, image->bbox);
+            return _rasterImage(surface, image->data, image->w, image->h, bbox);
         }
         else {
-            if (opacity < 255) return _rasterTranslucentImage(surface, image->data, image->w, image->h, opacity, image->bbox, &invTransform);
-            return _rasterImage(surface, image->data, image->w, image->h, image->bbox, &invTransform);
+            if (opacity < 255) return _rasterTranslucentImage(surface, image->data, image->w, image->h, opacity, bbox, &invTransform);
+            return _rasterImage(surface, image->data, image->w, image->h, bbox, &invTransform);
         }
     }
 }
\ No newline at end of file
index 580705f..c203891 100644 (file)
@@ -35,6 +35,7 @@ struct SwComposite
     SwSurface surface;
     SwSurface* recover;
     SwImage image;
+    SwBBox bbox;
     bool valid;
 };
 
@@ -46,6 +47,15 @@ struct SwTask : Task
     RenderUpdateFlag flags = RenderUpdateFlag::None;
     Array<Composite> compList;
     uint32_t opacity;
+    SwBBox bbox = {{0, 0}, {0, 0}};       //Whole Rendering Region
+
+    void bounds(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
+    {
+        if (x) *x = bbox.min.x;
+        if (y) *y = bbox.min.y;
+        if (w) *w = bbox.max.x - bbox.min.x;
+        if (h) *h = bbox.max.y - bbox.min.y;
+    }
 
     virtual bool dispose() = 0;
 };
@@ -86,7 +96,7 @@ struct SwShapeTask : SwTask
             bool renderShape = (alpha > 0 || sdata->fill());
             if (renderShape || strokeAlpha) {
                 shapeReset(&shape);
-                if (!shapePrepare(&shape, sdata, tid, clip, transform)) goto end;
+                if (!shapePrepare(&shape, sdata, tid, clip, transform, bbox)) goto end;
                 if (renderShape) {
                     /* We assume that if stroke width is bigger than 2,
                        shape outline below stroke could be full covered by stroke drawing.
@@ -114,7 +124,7 @@ struct SwShapeTask : SwTask
         if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
             if (strokeAlpha > 0) {
                 shapeResetStroke(&shape, sdata, transform);
-                if (!shapeGenStrokeRle(&shape, sdata, tid, transform, clip)) goto end;
+                if (!shapeGenStrokeRle(&shape, sdata, tid, transform, clip, bbox)) goto end;
                 ++addStroking;
             } else {
                 shapeDelStroke(&shape);
@@ -167,11 +177,11 @@ struct SwImageTask : SwTask
 
         if (prepareImage) {
             imageReset(&image);
-            if (!imagePrepare(&image, pdata, tid, clip, transform)) goto end;
+            if (!imagePrepare(&image, pdata, tid, clip, transform, bbox)) goto end;
 
             //Composition?
             if (compList.count > 0) {
-                if (!imageGenRle(&image, pdata, clip, false, true)) goto end;
+                if (!imageGenRle(&image, pdata, clip, bbox, false, true)) goto end;
                 if (image.rle) {
                     for (auto comp = compList.data; comp < (compList.data + compList.count); ++comp) {
                         if ((*comp).method == CompositeMethod::ClipPath) {
@@ -274,12 +284,21 @@ bool SwRenderer::postRender()
 }
 
 
+bool SwRenderer::renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
+{
+    static_cast<SwTask*>(data)->bounds(x, y, w, h);
+
+    return true;
+}
+
+
+
 bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data)
 {
     auto task = static_cast<SwImageTask*>(data);
     task->done();
 
-    return rasterImage(surface, &task->image, task->transform, task->opacity);
+    return rasterImage(surface, &task->image, task->transform, task->bbox, task->opacity);
 }
 
 
@@ -316,16 +335,10 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
     if (x + w > surface->w) w = (surface->w - x);
     if (y + h > surface->h) h = (surface->h - y);
 
-    //FIXME: Should be removed if xywh is proper.
-    x = 0;
-    y = 0;
-    w = surface->w;
-    h = surface->h;
-
-    comp->image.bbox.min.x = x;
-    comp->image.bbox.min.y = y;
-    comp->image.bbox.max.x = x + w;
-    comp->image.bbox.max.y = y + h;
+    comp->bbox.min.x = x;
+    comp->bbox.min.y = y;
+    comp->bbox.max.x = x + w;
+    comp->bbox.max.y = y + h;
     comp->image.w = surface->w;
     comp->image.h = surface->h;
 
@@ -362,7 +375,7 @@ bool SwRenderer::endComposite(void* p, uint32_t opacity)
     //Recover render target
     surface = comp->recover;
 
-    auto ret = rasterImage(surface, &comp->image, nullptr, opacity);
+    auto ret = rasterImage(surface, &comp->image, nullptr, comp->bbox, opacity);
 
     comp->valid = true;
 
@@ -382,12 +395,8 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
 
     //Do Composition
     if (task->compStroking) {
-        //Add stroke size to bounding box.
-        auto strokeWidth = static_cast<SwCoord>(ceilf(task->sdata->strokeWidth() * 0.5f));
-        auto x = task->shape.bbox.min.x - strokeWidth;
-        auto y = task->shape.bbox.min.y - strokeWidth;
-        auto w = task->shape.bbox.max.x + strokeWidth - x;
-        auto h = task->shape.bbox.max.y + strokeWidth - y;
+        uint32_t x, y, w, h;
+        task->bounds(&x, &y, &w, &h);
         ctx = beginComposite(x, y, w, h);
         opacity = 255;
     //No Composition
index 30bca7b..e3e600d 100644 (file)
@@ -43,6 +43,7 @@ public:
     bool dispose(void *data) override;
     bool preRender() override;
     bool postRender() override;
+    bool renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
     bool clear() override;
     bool render(const Shape& shape, void *data) override;
     bool render(const Picture& picture, void *data) override;
index eaef58e..c8edac0 100644 (file)
@@ -420,7 +420,7 @@ bool _fastTrack(const SwOutline* outline)
 /* External Class Implementation                                        */
 /************************************************************************/
 
-bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform)
+bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox)
 {
     if (!shapeGenOutline(shape, sdata, tid, transform)) return false;
 
@@ -428,6 +428,8 @@ bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize
 
     if (!_checkValid(shape->outline, shape->bbox, clip)) return false;
 
+    bbox = shape->bbox;
+
     return true;
 }
 
@@ -588,7 +590,7 @@ void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transfor
 }
 
 
-bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip)
+bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip, SwBBox& bbox)
 {
     SwOutline* shapeOutline = nullptr;
     SwOutline* strokeOutline = nullptr;
@@ -619,7 +621,6 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const M
         goto fail;
     }
 
-    SwBBox bbox;
     _updateBBox(strokeOutline, bbox);
 
     if (!_checkValid(strokeOutline, bbox, clip)) {
index 0d811a2..7c01a72 100644 (file)
@@ -37,6 +37,7 @@ namespace tvg
         virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag pFlag) = 0;   //Return engine data if it has.
         virtual bool render(RenderMethod& renderer) = 0;
         virtual bool bounds(float* x, float* y, float* w, float* h) const = 0;
+        virtual bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const = 0;
         virtual Paint* duplicate() = 0;
     };
 
@@ -125,6 +126,11 @@ namespace tvg
             return smethod->bounds(x, y, w, h);
         }
 
+        bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const
+        {
+            return smethod->bounds(renderer, x, y, w, h);
+        }
+
         bool dispose(RenderMethod& renderer)
         {
             if (compTarget) compTarget->pImpl->dispose(renderer);
@@ -212,6 +218,11 @@ namespace tvg
             return inst->bounds(x, y, w, h);
         }
 
+        bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const override
+        {
+            return inst->bounds(renderer, x, y, w, h);
+        }
+
         bool dispose(RenderMethod& renderer) override
         {
             return inst->dispose(renderer);
index 0e52963..c84b04b 100644 (file)
@@ -153,6 +153,13 @@ struct Picture::Impl
         return paint->pImpl->bounds(x, y, w, h);
     }
 
+    bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
+    {
+        if (edata) return renderer.renderRegion(edata, x, y, w, h);
+        if (paint) paint->pImpl->bounds(renderer, x, y, w, h);
+        return false;
+    }
+
     Result load(const string& path)
     {
         if (loader) loader->close();
index 383f678..6557ff0 100644 (file)
@@ -74,6 +74,7 @@ public:
     virtual bool render(const Shape& shape, void *data) = 0;
     virtual bool render(const Picture& picture, void *data) = 0;
     virtual bool postRender() = 0;
+    virtual bool renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) = 0;
     virtual bool clear() = 0;
     virtual bool sync() = 0;
 };
index 9a9f36c..71b17f2 100644 (file)
@@ -63,17 +63,15 @@ struct Scene::Impl
         return edata;
     }
 
-    bool render(RenderMethod &renderer)
+    bool render(RenderMethodrenderer)
     {
         void* ctx = nullptr;
 
         //Half translucent. This requires intermediate composition.
         if (opacity < 255 && opacity > 0) {
-            //FIXME: Get Render Boundary of Shapes.
-            //float x, y, w, h;
-            //if (!bounds(&x, &y, &w, &h)) return false;
-            //ctx = renderer.beginComposite(roundf(x), roundf(y), roundf(w), roundf(h));
-            ctx = renderer.beginComposite(0, 0, 0, 0);
+            uint32_t x, y, w, h;
+            if (!bounds(renderer, &x, &y, &w, &h)) return false;
+            ctx = renderer.beginComposite(x, y, w, h);
         }
 
         for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
@@ -85,6 +83,38 @@ struct Scene::Impl
         return true;
     }
 
+    bool bounds(RenderMethod& renderer, uint32_t* px, uint32_t* py, uint32_t* pw, uint32_t* ph)
+    {
+        if (paints.count == 0) return false;
+
+        uint32_t x1 = UINT32_MAX;
+        uint32_t y1 = UINT32_MAX;
+        uint32_t x2 = 0;
+        uint32_t y2 = 0;
+
+        for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
+            uint32_t x = UINT32_MAX;
+            uint32_t y = UINT32_MAX;
+            uint32_t w = 0;
+            uint32_t h = 0;
+
+            if (!(*paint)->pImpl->bounds(renderer, &x, &y, &w, &h)) continue;
+
+            //Merge regions
+            if (x < x1) x1 = x;
+            if (x2 < x + w) x2 = (x + w);
+            if (y < y1) y1 = y;
+            if (y2 < y + h) y2 = (y + h);
+        }
+
+        if (px) *px = x1;
+        if (py) *py = y1;
+        if (pw) *pw = (x2 - x1);
+        if (ph) *ph = (y2 - y1);
+
+        return true;
+    }
+
     bool bounds(float* px, float* py, float* pw, float* ph)
     {
         if (paints.count == 0) return false;
index 7df1425..f5a2dfa 100644 (file)
@@ -230,6 +230,11 @@ struct Shape::Impl
         return this->edata;
     }
 
+    bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
+    {
+        return renderer.renderRegion(edata, x, y, w, h);
+    }
+
     bool bounds(float* x, float* y, float* w, float* h)
     {
         auto ret = path.bounds(x, y, w, h);