7c3ca8d179257daab7d9055176eb9ba946b2ebfb
[platform/core/graphics/tizenvg.git] / src / lib / sw_engine / tvgSwRenderer.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *               http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  */
17 #ifndef _TVG_SW_RENDERER_CPP_
18 #define _TVG_SW_RENDERER_CPP_
19
20 using namespace std;
21
22 #include "tvgSwCommon.h"
23 #include "tvgSwRenderer.h"
24
25
26 /************************************************************************/
27 /* Internal Class Implementation                                        */
28 /************************************************************************/
29 namespace tvg {
30     struct SwTask
31     {
32         SwShape shape;
33         const Shape* sdata;
34         SwSize clip;
35         Matrix* transform;
36         RenderUpdateFlag flags;
37         future<void> progress;
38     };
39 }
40
41 static RenderInitializer renderInit;
42
43
44 /************************************************************************/
45 /* External Class Implementation                                        */
46 /************************************************************************/
47
48 SwRenderer::~SwRenderer()
49 {
50     flush();
51 }
52
53
54 bool SwRenderer::clear()
55 {
56     return flush();
57 }
58
59
60 bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h)
61 {
62     if (!buffer || stride == 0 || w == 0 || h == 0) return false;
63
64     surface.buffer = buffer;
65     surface.stride = stride;
66     surface.w = w;
67     surface.h = h;
68
69     return true;
70 }
71
72
73 bool SwRenderer::preRender()
74 {
75     //before we start rendering, we should finish all preparing tasks
76     while (prepareTasks.size() > 0) {
77         auto task = prepareTasks.front();
78         if (task->progress.valid()) task->progress.get();
79         prepareTasks.pop();
80         renderTasks.push(task);
81     }
82     return true;
83 }
84
85
86 bool SwRenderer::postRender()
87 {
88     auto asyncTask = [](SwRenderer* renderer) {
89         renderer->doRender();
90     };
91
92     progress = async(launch::async, asyncTask, this);
93
94     return true;
95 }
96
97
98 void SwRenderer::doRender()
99 {
100     rasterClear(surface);
101
102     while (renderTasks.size() > 0) {
103         auto task = renderTasks.front();
104         uint8_t r, g, b, a;
105         if (auto fill = task->sdata->fill()) {
106             rasterGradientShape(surface, task->shape, fill->id());
107         } else{
108             task->sdata->fill(&r, &g, &b, &a);
109             if (a > 0) rasterSolidShape(surface, task->shape, r, g, b, a);
110         }
111         task->sdata->strokeColor(&r, &g, &b, &a);
112        if (a > 0) rasterStroke(surface, task->shape, r, g, b, a);
113         renderTasks.pop();
114     }
115 }
116
117
118 bool SwRenderer::flush()
119 {
120     while (prepareTasks.size() > 0) {
121         auto task = prepareTasks.front();
122         if (task->progress.valid()) task->progress.get();
123         prepareTasks.pop();
124     }
125
126     if (progress.valid()) progress.get();
127
128     return true;
129 }
130
131
132 bool SwRenderer::render(const Shape& sdata, void *data)
133 {
134     //Do Nothing
135
136     return true;
137 }
138
139
140 bool SwRenderer::dispose(const Shape& sdata, void *data)
141 {
142     auto task = static_cast<SwTask*>(data);
143     if (!task) return true;
144     if (task->progress.valid()) task->progress.get();
145     shapeFree(task->shape);
146     if (task->transform) free(task->transform);
147     free(task);
148     return true;
149 }
150
151
152 void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
153 {
154     //prepare task
155     auto task = static_cast<SwTask*>(data);
156     if (!task) {
157         task = static_cast<SwTask*>(calloc(1, sizeof(SwTask)));
158         if (!task) return nullptr;
159     }
160
161     if (flags == RenderUpdateFlag::None || task->progress.valid()) return task;
162
163     task->sdata = &sdata;
164     task->clip = {static_cast<SwCoord>(surface.w), static_cast<SwCoord>(surface.h)};
165
166     if (transform) {
167         if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix)));
168         assert(task->transform);
169         *task->transform = transform->m;
170     } else {
171         if (task->transform) free(task->transform);
172         task->transform = nullptr;
173     }
174
175     task->flags = flags;
176
177     auto asyncTask = [](SwTask* task) {
178
179         //Valid Stroking?
180         uint8_t strokeAlpha = 0;
181         auto strokeWidth = task->sdata->strokeWidth();
182         if (strokeWidth > FLT_EPSILON) {
183             task->sdata->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha);
184         }
185
186         //Shape
187         if (task->flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) {
188             shapeReset(task->shape);
189             uint8_t alpha = 0;
190             task->sdata->fill(nullptr, nullptr, nullptr, &alpha);
191             bool renderShape = (alpha > 0 || task->sdata->fill());
192             if (renderShape || strokeAlpha) {
193                 if (!shapePrepare(task->shape, task->sdata, task->clip, task->transform)) return;
194                 if (renderShape) {
195                     auto antiAlias = (strokeAlpha > 0 && strokeWidth >= 2) ? false : true;
196                     if (!shapeGenRle(task->shape, task->sdata, task->clip, antiAlias)) return;
197                 }
198             }
199         }
200         //Fill
201         if (task->flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
202             auto fill = task->sdata->fill();
203             if (fill) {
204                 auto ctable = (task->flags & RenderUpdateFlag::Gradient) ? true : false;
205                 if (ctable) shapeResetFill(task->shape);
206                 if (!shapeGenFillColors(task->shape, fill, task->transform, ctable)) return;
207             } else {
208                 shapeDelFill(task->shape);
209             }
210         }
211         //Stroke
212         if (task->flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
213             if (strokeAlpha > 0) {
214                 shapeResetStroke(task->shape, task->sdata);
215                 if (!shapeGenStrokeRle(task->shape, task->sdata, task->transform, task->clip)) return;
216             } else {
217                 shapeDelStroke(task->shape);
218             }
219         }
220         shapeDelOutline(task->shape);
221     };
222
223     prepareTasks.push(task);
224     task->progress = async((launch::async | launch::deferred), asyncTask, task);
225
226     return task;
227 }
228
229
230 int SwRenderer::init()
231 {
232     return RenderInitializer::init(renderInit, new SwRenderer);
233 }
234
235
236 int SwRenderer::term()
237 {
238     return RenderInitializer::term(renderInit);
239 }
240
241
242 uint32_t SwRenderer::unref()
243 {
244     return RenderInitializer::unref(renderInit);
245 }
246
247
248 uint32_t SwRenderer::ref()
249 {
250     return RenderInitializer::ref(renderInit);
251 }
252
253
254 SwRenderer* SwRenderer::inst()
255 {
256     //We know renderer type, avoid dynamic_cast for performance.
257     return static_cast<SwRenderer*>(RenderInitializer::inst(renderInit));
258 }
259
260 #endif /* _TVG_SW_RENDERER_CPP_ */