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
}
+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)
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;
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?
};
SwOutline* outline = nullptr;
SwRleData* rle = nullptr;
uint32_t* data = nullptr;
- SwBBox bbox;
uint32_t w, h;
};
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);
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);
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);
/************************************************************************/
-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;
}
}
-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;
}
{
rleReset(image->rle);
image->rle = nullptr;
- _initBBox(image->bbox);
}
}
-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;
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
SwSurface surface;
SwSurface* recover;
SwImage image;
+ SwBBox bbox;
bool valid;
};
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;
};
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.
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);
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) {
}
+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);
}
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;
//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;
//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
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;
/* 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;
if (!_checkValid(shape->outline, shape->bbox, clip)) return false;
+ bbox = shape->bbox;
+
return true;
}
}
-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;
goto fail;
}
- SwBBox bbox;
_updateBBox(strokeOutline, bbox);
if (!_checkValid(strokeOutline, bbox, clip)) {
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;
};
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);
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);
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();
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;
};
return edata;
}
- bool render(RenderMethod &renderer)
+ bool render(RenderMethod& renderer)
{
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) {
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;
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);