2 * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef _TVG_SW_RENDERER_CPP_
18 #define _TVG_SW_RENDERER_CPP_
22 #include "tvgSwCommon.h"
23 #include "tvgSwRenderer.h"
26 /************************************************************************/
27 /* Internal Class Implementation */
28 /************************************************************************/
36 RenderUpdateFlag flags;
37 future<void> progress;
41 static RenderInitializer renderInit;
44 /************************************************************************/
45 /* External Class Implementation */
46 /************************************************************************/
48 SwRenderer::~SwRenderer()
54 bool SwRenderer::clear()
60 bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h)
62 if (!buffer || stride == 0 || w == 0 || h == 0) return false;
64 surface.buffer = buffer;
65 surface.stride = stride;
73 bool SwRenderer::preRender()
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();
80 renderTasks.push(task);
86 bool SwRenderer::postRender()
88 auto asyncTask = [](SwRenderer* renderer) {
92 progress = async(launch::async, asyncTask, this);
98 void SwRenderer::doRender()
100 rasterClear(surface);
102 while (renderTasks.size() > 0) {
103 auto task = renderTasks.front();
105 if (auto fill = task->sdata->fill()) {
106 rasterGradientShape(surface, task->shape, fill->id());
108 task->sdata->fill(&r, &g, &b, &a);
109 if (a > 0) rasterSolidShape(surface, task->shape, r, g, b, a);
111 task->sdata->strokeColor(&r, &g, &b, &a);
112 if (a > 0) rasterStroke(surface, task->shape, r, g, b, a);
118 bool SwRenderer::flush()
120 while (prepareTasks.size() > 0) {
121 auto task = prepareTasks.front();
122 if (task->progress.valid()) task->progress.get();
126 if (progress.valid()) progress.get();
132 bool SwRenderer::render(const Shape& sdata, void *data)
140 bool SwRenderer::dispose(const Shape& sdata, void *data)
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);
152 void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
155 auto task = static_cast<SwTask*>(data);
157 task = static_cast<SwTask*>(calloc(1, sizeof(SwTask)));
158 if (!task) return nullptr;
161 if (flags == RenderUpdateFlag::None || task->progress.valid()) return task;
163 task->sdata = &sdata;
164 task->clip = {static_cast<SwCoord>(surface.w), static_cast<SwCoord>(surface.h)};
167 if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix)));
168 assert(task->transform);
169 *task->transform = transform->m;
171 if (task->transform) free(task->transform);
172 task->transform = nullptr;
177 auto asyncTask = [](SwTask* task) {
180 uint8_t strokeAlpha = 0;
181 auto strokeWidth = task->sdata->strokeWidth();
182 if (strokeWidth > FLT_EPSILON) {
183 task->sdata->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha);
187 if (task->flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) {
188 shapeReset(task->shape);
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;
195 auto antiAlias = (strokeAlpha > 0 && strokeWidth >= 2) ? false : true;
196 if (!shapeGenRle(task->shape, task->sdata, task->clip, antiAlias)) return;
201 if (task->flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
202 auto fill = task->sdata->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;
208 shapeDelFill(task->shape);
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;
217 shapeDelStroke(task->shape);
220 shapeDelOutline(task->shape);
223 prepareTasks.push(task);
224 task->progress = async((launch::async | launch::deferred), asyncTask, task);
230 int SwRenderer::init()
232 return RenderInitializer::init(renderInit, new SwRenderer);
236 int SwRenderer::term()
238 return RenderInitializer::term(renderInit);
242 uint32_t SwRenderer::unref()
244 return RenderInitializer::unref(renderInit);
248 uint32_t SwRenderer::ref()
250 return RenderInitializer::ref(renderInit);
254 SwRenderer* SwRenderer::inst()
256 //We know renderer type, avoid dynamic_cast for performance.
257 return static_cast<SwRenderer*>(RenderInitializer::inst(renderInit));
260 #endif /* _TVG_SW_RENDERER_CPP_ */