From 37d34eeb19c22f5944ad843e2179dee4b94f0abd Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sun, 19 Apr 2020 13:13:27 +0900 Subject: [PATCH] sw_engine: concrete shape rendering sequence. Succeed first sw backend screen up! Change-Id: I882fb1726ed1f45e92e73fbc36170e93645dfbd2 --- inc/tizenvg.h | 11 +++---- src/lib/gl_engine/tvgGlRenderer.cpp | 23 ++++++++++++-- src/lib/gl_engine/tvgGlRenderer.h | 3 +- src/lib/sw_engine/meson.build | 1 + src/lib/sw_engine/tvgSwCommon.h | 2 ++ src/lib/sw_engine/tvgSwRaster.cpp | 42 +++++++++++++++++++++++++ src/lib/sw_engine/tvgSwRenderer.cpp | 39 +++++++++++++++++++++--- src/lib/sw_engine/tvgSwRenderer.h | 6 +++- src/lib/tvgCanvasBase.h | 61 +++++++++++++++++++++++-------------- src/lib/tvgGlCanvas.cpp | 13 ++++++-- src/lib/tvgRenderCommon.h | 11 ++++++- src/lib/tvgSceneNode.cpp | 15 +++------ src/lib/tvgShapeNode.cpp | 23 ++++++-------- src/lib/tvgSwCanvas.cpp | 17 +++++------ test/testShape.cpp | 2 +- 15 files changed, 193 insertions(+), 76 deletions(-) create mode 100644 src/lib/sw_engine/tvgSwRaster.cpp diff --git a/inc/tizenvg.h b/inc/tizenvg.h index dd125b5..24f2d3f 100644 --- a/inc/tizenvg.h +++ b/inc/tizenvg.h @@ -56,8 +56,7 @@ class RenderMethod; struct Point { - float x; - float y; + float x, y; }; @@ -73,7 +72,6 @@ class TIZENVG_EXPORT PaintNode { public: virtual ~PaintNode() {} - virtual int dispose(RenderMethod* engine) = 0; virtual int update(RenderMethod* engine) = 0; }; @@ -91,7 +89,6 @@ class TIZENVG_EXPORT ShapeNode final : public PaintNode public: ~ShapeNode(); - int dispose(RenderMethod* engine) noexcept override; int update(RenderMethod* engine) noexcept override; int clear() noexcept; @@ -106,6 +103,9 @@ public: static std::unique_ptr gen() noexcept; + //FIXME: Ugly... Better design? + void *engine() noexcept; + _TIZENVG_DECLARE_PRIVATE(ShapeNode); }; @@ -123,7 +123,6 @@ class TIZENVG_EXPORT SceneNode final : public PaintNode public: ~SceneNode(); - int dispose(RenderMethod* engine) noexcept override; int update(RenderMethod* engine) noexcept override; int push(std::unique_ptr shape) noexcept; @@ -181,7 +180,7 @@ public: //TODO: Gl Specific methods. Need gl backend configuration methods as well. int update() noexcept; - int draw(bool async = true) noexcept { return 0; } + int draw(bool async = true) noexcept; int sync() noexcept { return 0; } RenderMethod* engine() noexcept; diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index 2357539..38fb4de 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -35,12 +35,26 @@ struct GlShape /* External Class Implementation */ /************************************************************************/ -void* GlRenderer::dispose(const ShapeNode& shape, void *data) +bool GlRenderer::render(const ShapeNode& shape, void *data) { GlShape* sdata = static_cast(data); - if (!sdata) return nullptr; + if (!sdata) return false; + + //TODO: + + return true; +} + + +bool GlRenderer::dispose(const ShapeNode& shape, void *data) +{ + GlShape* sdata = static_cast(data); + if (!sdata) return false; + + //TODO: + free(sdata); - return nullptr; + return true; } @@ -52,6 +66,9 @@ void* GlRenderer::prepare(const ShapeNode& shape, void* data, UpdateFlag flags) sdata = static_cast(calloc(1, sizeof(GlShape))); assert(sdata); } + + //TODO: + return sdata; } diff --git a/src/lib/gl_engine/tvgGlRenderer.h b/src/lib/gl_engine/tvgGlRenderer.h index 534969a..881d1ef 100644 --- a/src/lib/gl_engine/tvgGlRenderer.h +++ b/src/lib/gl_engine/tvgGlRenderer.h @@ -24,7 +24,8 @@ class GlRenderer : public RenderMethod { public: void* prepare(const ShapeNode& shape, void* data, UpdateFlag flags) override; - void* dispose(const ShapeNode& shape, void *data) override; + bool dispose(const ShapeNode& shape, void *data) override; + bool render(const ShapeNode& shape, void *data) override; size_t ref() override; size_t unref() override; diff --git a/src/lib/sw_engine/meson.build b/src/lib/sw_engine/meson.build index 4edd489..a33059d 100644 --- a/src/lib/sw_engine/meson.build +++ b/src/lib/sw_engine/meson.build @@ -4,6 +4,7 @@ source_file = [ 'tvgSwRenderer.cpp', 'tvgSwShape.cpp', 'tvgSwRle.cpp', + 'tvgSwRaster.cpp', ] swraster_dep = declare_dependency( diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 4e75e3c..4b6f820 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -95,4 +95,6 @@ bool shapeTransformOutline(const ShapeNode& shape, SwShape& sdata); SwRleData* rleRender(const SwShape& sdata); +bool rasterShape(Surface& surface, SwShape& sdata, size_t color); + #endif /* _TVG_SW_COMMON_H_ */ diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp new file mode 100644 index 0000000..2e43a44 --- /dev/null +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _TVG_SW_RASTER_CPP_ +#define _TVG_SW_RASTER_CPP_ + +#include "tvgSwCommon.h" + + +bool rasterShape(Surface& surface, SwShape& sdata, size_t color) +{ + SwRleData* rle = sdata.rle; + assert(rle); + + auto stride = surface.stride; + auto span = rle->spans; + + for (size_t i = 0; i < rle->size; ++i) { + assert(span); + for (auto j = 0; j < span->len; ++j) { + surface.buffer[span->y * stride + span->x + j] = color; + } + ++span; + } + + return true; +} + +#endif /* _TVG_SW_RASTER_CPP_ */ \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 0e09da6..425afab 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -26,18 +26,49 @@ static RenderInitializer renderInit; +static inline size_t COLOR(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return (a << 24 | r << 16 | g << 8 | b); +} /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -void* SwRenderer::dispose(const ShapeNode& shape, void *data) +bool SwRenderer::target(uint32_t* buffer, size_t stride, size_t height) +{ + assert(buffer && stride > 0 && height > 0); + + surface.buffer = buffer; + surface.stride = stride; + surface.height = height; + + return true; +} + + +bool SwRenderer::render(const ShapeNode& shape, void *data) +{ + SwShape* sdata = static_cast(data); + if (!sdata) return false; + + //invisible? + size_t r, g, b, a; + shape.fill(&r, &g, &b, &a); + if (a == 0) return true; + + //TODO: Threading + return rasterShape(surface, *sdata, COLOR(r, g, b, a)); +} + + +bool SwRenderer::dispose(const ShapeNode& shape, void *data) { SwShape* sdata = static_cast(data); - if (!sdata) return nullptr; + if (!sdata) return false; shapeReset(*sdata); free(sdata); - return nullptr; + return true; } void* SwRenderer::prepare(const ShapeNode& shape, void* data, UpdateFlag flags) @@ -56,10 +87,10 @@ void* SwRenderer::prepare(const ShapeNode& shape, void* data, UpdateFlag flags) shape.fill(nullptr, nullptr, nullptr, &alpha); if (alpha == 0) return sdata; + //TODO: Threading if (flags & UpdateFlag::Path) { shapeReset(*sdata); if (!shapeGenOutline(shape, *sdata)) return sdata; - //TODO: From below sequence starts threading? if (!shapeTransformOutline(shape, *sdata)) return sdata; if (!shapeGenRle(shape, *sdata)) return sdata; } diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 13f4f27..f8ce1d4 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -20,8 +20,12 @@ class SwRenderer : public RenderMethod { public: + Surface surface; + void* prepare(const ShapeNode& shape, void* data, UpdateFlag flags) override; - void* dispose(const ShapeNode& shape, void *data) override; + bool dispose(const ShapeNode& shape, void *data) override; + bool render(const ShapeNode& shape, void *data) override; + bool target(uint32_t* buffer, size_t stride, size_t height); size_t ref() override; size_t unref() override; diff --git a/src/lib/tvgCanvasBase.h b/src/lib/tvgCanvasBase.h index 89476ad..a2ed34b 100644 --- a/src/lib/tvgCanvasBase.h +++ b/src/lib/tvgCanvasBase.h @@ -19,9 +19,6 @@ #include "tvgCommon.h" -/************************************************************************/ -/* Internal Class Implementation */ -/************************************************************************/ struct CanvasBase { @@ -48,42 +45,60 @@ struct CanvasBase int clear() { + assert(renderer); + + auto ret = 0; + for (auto node : nodes) { - node->dispose(renderer); + if (SceneNode *scene = dynamic_cast(node)) { + cout << "TODO: " << scene << endl; + } else if (ShapeNode *shape = dynamic_cast(node)) { + ret |= renderer->dispose(*shape, shape->engine()); + } delete(node); } nodes.clear(); - return 0; + return ret; + } + + int update() + { + assert(renderer); + + auto ret = 0; + + for(auto node: nodes) { + ret |= node->update(renderer); + } + + return ret; } int push(unique_ptr paint) { PaintNode *node = paint.release(); assert(node); - nodes.push_back(node); -#if 0 - if (SceneNode *scene = dynamic_cast(node)) { + return node->update(renderer); + } - } else if (ShapeNode *shape = dynamic_cast(node)) { - return shape->update(renderer); - } -#else - if (ShapeNode *shape = dynamic_cast(node)) { - return shape->update(renderer); - } -#endif - cout << "What type of PaintNode? = " << node << endl; + int draw() + { + assert(renderer); - return -1; + auto ret = 0; + + for(auto node: nodes) { + if (SceneNode *scene = dynamic_cast(node)) { + cout << "TODO: " << scene << endl; + } else if (ShapeNode *shape = dynamic_cast(node)) { + ret |= renderer->render(*shape, shape->engine()); + } + } + return ret; } }; - -/************************************************************************/ -/* External Class Implementation */ -/************************************************************************/ - #endif /* _TVG_CANVAS_BASE_CPP_ */ diff --git a/src/lib/tvgGlCanvas.cpp b/src/lib/tvgGlCanvas.cpp index 619ea4b..386778d 100644 --- a/src/lib/tvgGlCanvas.cpp +++ b/src/lib/tvgGlCanvas.cpp @@ -42,7 +42,6 @@ GlCanvas::GlCanvas() : pImpl(make_unique()) GlCanvas::~GlCanvas() { - cout << "GlCanvas(" << this << ") destroyed!" << endl; } @@ -72,7 +71,9 @@ int GlCanvas::clear() noexcept int GlCanvas::update() noexcept { - return 0; + auto impl = pImpl.get(); + assert(impl); + return impl->update(); } @@ -83,4 +84,12 @@ RenderMethod* GlCanvas::engine() noexcept return impl->renderer; } + +int GlCanvas::draw(bool async) noexcept +{ + auto impl = pImpl.get(); + assert(impl); + return impl->draw(); +} + #endif /* _TVG_GLCANVAS_CPP_ */ diff --git a/src/lib/tvgRenderCommon.h b/src/lib/tvgRenderCommon.h index e06f1ac..acdfc2f 100644 --- a/src/lib/tvgRenderCommon.h +++ b/src/lib/tvgRenderCommon.h @@ -20,13 +20,22 @@ namespace tvg { +struct Surface +{ + //TODO: Union for multiple types + uint32_t* buffer; + size_t stride; + size_t height; +}; + class RenderMethod { public: enum UpdateFlag { None = 0, Path = 1, Fill = 2, All = 3 }; virtual ~RenderMethod() {} virtual void* prepare(const ShapeNode& shape, void* data, UpdateFlag flags) = 0; - virtual void* dispose(const ShapeNode& shape, void *data) = 0; + virtual bool dispose(const ShapeNode& shape, void *data) = 0; + virtual bool render(const ShapeNode& shape, void *data) = 0; virtual size_t ref() = 0; virtual size_t unref() = 0; }; diff --git a/src/lib/tvgSceneNode.cpp b/src/lib/tvgSceneNode.cpp index 9c7d11f..db3ae1d 100644 --- a/src/lib/tvgSceneNode.cpp +++ b/src/lib/tvgSceneNode.cpp @@ -34,13 +34,13 @@ struct SceneNode::Impl /* External Class Implementation */ /************************************************************************/ -SceneNode :: SceneNode() : pImpl(make_unique()) +SceneNode::SceneNode() : pImpl(make_unique()) { } -SceneNode :: ~SceneNode() +SceneNode::~SceneNode() { cout << "SceneNode(" << this << ") destroyed!" << endl; } @@ -52,20 +52,13 @@ unique_ptr SceneNode::gen() noexcept } -int SceneNode :: push(unique_ptr shape) noexcept +int SceneNode::push(unique_ptr shape) noexcept { return 0; } -int SceneNode :: dispose(RenderMethod* engine) noexcept -{ - - return 0; -} - - -int SceneNode :: update(RenderMethod* engine) noexcept +int SceneNode::update(RenderMethod* engine) noexcept { return 0; diff --git a/src/lib/tvgShapeNode.cpp b/src/lib/tvgShapeNode.cpp index 74dae23..2c15b1b 100644 --- a/src/lib/tvgShapeNode.cpp +++ b/src/lib/tvgShapeNode.cpp @@ -84,18 +84,15 @@ unique_ptr ShapeNode::gen() noexcept } -int ShapeNode :: dispose(RenderMethod* engine) noexcept +void* ShapeNode::engine() noexcept { auto impl = pImpl.get(); assert(impl); - - impl->edata = engine->dispose(*this, impl->edata); - if (impl->edata) return -1; - return 0; + return impl->edata; } -int ShapeNode :: update(RenderMethod* engine) noexcept +int ShapeNode::update(RenderMethod* engine) noexcept { auto impl = pImpl.get(); assert(impl); @@ -106,7 +103,7 @@ int ShapeNode :: update(RenderMethod* engine) noexcept } -int ShapeNode :: clear() noexcept +int ShapeNode::clear() noexcept { auto impl = pImpl.get(); assert(impl); @@ -115,7 +112,7 @@ int ShapeNode :: clear() noexcept } -int ShapeNode :: pathCommands(const PathCommand** cmds) const noexcept +int ShapeNode::pathCommands(const PathCommand** cmds) const noexcept { auto impl = pImpl.get(); assert(impl && cmds); @@ -126,7 +123,7 @@ int ShapeNode :: pathCommands(const PathCommand** cmds) const noexcept } -int ShapeNode :: pathCoords(const Point** pts) const noexcept +int ShapeNode::pathCoords(const Point** pts) const noexcept { auto impl = pImpl.get(); assert(impl && pts); @@ -137,13 +134,13 @@ int ShapeNode :: pathCoords(const Point** pts) const noexcept } -int ShapeNode :: appendCircle(float cx, float cy, float radius) noexcept +int ShapeNode::appendCircle(float cx, float cy, float radius) noexcept { return 0; } -int ShapeNode :: appendRect(float x, float y, float w, float h, float radius) noexcept +int ShapeNode::appendRect(float x, float y, float w, float h, float radius) noexcept { auto impl = pImpl.get(); assert(impl); @@ -171,7 +168,7 @@ int ShapeNode :: appendRect(float x, float y, float w, float h, float radius) no } -int ShapeNode :: fill(size_t r, size_t g, size_t b, size_t a) noexcept +int ShapeNode::fill(size_t r, size_t g, size_t b, size_t a) noexcept { auto impl = pImpl.get(); assert(impl); @@ -185,7 +182,7 @@ int ShapeNode :: fill(size_t r, size_t g, size_t b, size_t a) noexcept } -int ShapeNode :: fill(size_t* r, size_t* g, size_t* b, size_t* a) const noexcept +int ShapeNode::fill(size_t* r, size_t* g, size_t* b, size_t* a) const noexcept { auto impl = pImpl.get(); assert(impl); diff --git a/src/lib/tvgSwCanvas.cpp b/src/lib/tvgSwCanvas.cpp index 4d930a7..442b0d7 100644 --- a/src/lib/tvgSwCanvas.cpp +++ b/src/lib/tvgSwCanvas.cpp @@ -28,10 +28,6 @@ struct SwCanvas::Impl : CanvasBase { - uint32_t* buffer = nullptr; - int stride = 0; - int height = 0; - Impl() : CanvasBase(SwRenderer::inst()) {} }; @@ -45,9 +41,7 @@ int SwCanvas::target(uint32_t* buffer, size_t stride, size_t height) noexcept auto impl = pImpl.get(); assert(impl); - impl->buffer = buffer; - impl->stride = stride; - impl->height = height; + dynamic_cast(impl->renderer)->target(buffer, stride, height); return 0; } @@ -55,7 +49,9 @@ int SwCanvas::target(uint32_t* buffer, size_t stride, size_t height) noexcept int SwCanvas::draw(bool async) noexcept { - return 0; + auto impl = pImpl.get(); + assert(impl); + return impl->draw(); } @@ -89,7 +85,6 @@ SwCanvas::SwCanvas() : pImpl(make_unique()) SwCanvas::~SwCanvas() { - cout << "SwCanvas(" << this << ") destroyed!" << endl; } @@ -107,7 +102,9 @@ unique_ptr SwCanvas::gen(uint32_t* buffer, size_t stride, size_t heigh int SwCanvas::update() noexcept { - return 0; + auto impl = pImpl.get(); + assert(impl); + return impl->update(); } diff --git a/test/testShape.cpp b/test/testShape.cpp index 4ee2ad7..e42cba8 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -19,7 +19,7 @@ void tvgtest() //Prepare a Shape (Rectangle) auto shape1 = tvg::ShapeNode::gen(); shape1->appendRect(0, 0, 400, 400, 0); //x, y, w, h, corner_radius - shape1->fill(0, 255, 0, 255); //r, g, b, a + shape1->fill(255, 0, 0, 255); //r, g, b, a /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare -- 2.7.4