|
@@ -28,10 +28,14 @@
|
|
|
|
|
|
struct Canvas::Impl
|
|
|
{
|
|
|
+ enum Status : uint8_t {Synced = 0, Updating, Drawing};
|
|
|
+
|
|
|
list<Paint*> paints;
|
|
|
RenderMethod* renderer;
|
|
|
+ RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX};
|
|
|
+ Status status = Status::Synced;
|
|
|
+
|
|
|
bool refresh = false; //if all paints should be updated by force.
|
|
|
- bool drawing = false; //on drawing condition?
|
|
|
|
|
|
Impl(RenderMethod* pRenderer) : renderer(pRenderer)
|
|
|
{
|
|
@@ -41,14 +45,12 @@ struct Canvas::Impl
|
|
|
~Impl()
|
|
|
{
|
|
|
//make it sure any deffered jobs
|
|
|
- if (renderer) {
|
|
|
- renderer->sync();
|
|
|
- renderer->clear();
|
|
|
- }
|
|
|
+ renderer->sync();
|
|
|
+ renderer->clear();
|
|
|
|
|
|
clearPaints();
|
|
|
|
|
|
- if (renderer && (renderer->unref() == 0)) delete(renderer);
|
|
|
+ if (renderer->unref() == 0) delete(renderer);
|
|
|
}
|
|
|
|
|
|
void clearPaints()
|
|
@@ -62,7 +64,7 @@ struct Canvas::Impl
|
|
|
Result push(unique_ptr<Paint> paint)
|
|
|
{
|
|
|
//You can not push paints during rendering.
|
|
|
- if (drawing) return Result::InsufficientCondition;
|
|
|
+ if (status == Status::Drawing) return Result::InsufficientCondition;
|
|
|
|
|
|
auto p = paint.release();
|
|
|
if (!p) return Result::MemoryCorruption;
|
|
@@ -75,12 +77,12 @@ struct Canvas::Impl
|
|
|
Result clear(bool free)
|
|
|
{
|
|
|
//Clear render target before drawing
|
|
|
- if (!renderer || !renderer->clear()) return Result::InsufficientCondition;
|
|
|
+ if (!renderer->clear()) return Result::InsufficientCondition;
|
|
|
|
|
|
//Free paints
|
|
|
if (free) clearPaints();
|
|
|
|
|
|
- drawing = false;
|
|
|
+ status = Status::Synced;
|
|
|
|
|
|
return Result::Success;
|
|
|
}
|
|
@@ -92,7 +94,7 @@ struct Canvas::Impl
|
|
|
|
|
|
Result update(Paint* paint, bool force)
|
|
|
{
|
|
|
- if (paints.empty() || drawing || !renderer) return Result::InsufficientCondition;
|
|
|
+ if (paints.empty() || status == Status::Drawing) return Result::InsufficientCondition;
|
|
|
|
|
|
Array<RenderData> clips;
|
|
|
auto flag = RenderUpdateFlag::None;
|
|
@@ -106,12 +108,13 @@ struct Canvas::Impl
|
|
|
}
|
|
|
refresh = false;
|
|
|
}
|
|
|
+ status = Status::Updating;
|
|
|
return Result::Success;
|
|
|
}
|
|
|
|
|
|
Result draw()
|
|
|
{
|
|
|
- if (drawing || paints.empty() || !renderer || !renderer->preRender()) return Result::InsufficientCondition;
|
|
|
+ if (status == Status::Drawing || paints.empty() || !renderer->preRender()) return Result::InsufficientCondition;
|
|
|
|
|
|
bool rendered = false;
|
|
|
for (auto paint : paints) {
|
|
@@ -120,22 +123,37 @@ struct Canvas::Impl
|
|
|
|
|
|
if (!rendered || !renderer->postRender()) return Result::InsufficientCondition;
|
|
|
|
|
|
- drawing = true;
|
|
|
-
|
|
|
+ status = Status::Drawing;
|
|
|
return Result::Success;
|
|
|
}
|
|
|
|
|
|
Result sync()
|
|
|
{
|
|
|
- if (!drawing) return Result::InsufficientCondition;
|
|
|
+ if (status == Status::Synced) return Result::InsufficientCondition;
|
|
|
|
|
|
if (renderer->sync()) {
|
|
|
- drawing = false;
|
|
|
+ status = Status::Synced;
|
|
|
return Result::Success;
|
|
|
}
|
|
|
|
|
|
return Result::InsufficientCondition;
|
|
|
}
|
|
|
+
|
|
|
+ Result viewport(int32_t x, int32_t y, int32_t w, int32_t h)
|
|
|
+ {
|
|
|
+ if (status != Status::Synced) return Result::InsufficientCondition;
|
|
|
+ RenderRegion val = {x, y, w, h};
|
|
|
+ //intersect if the target buffer is already set.
|
|
|
+ auto surface = renderer->mainSurface();
|
|
|
+ if (surface && surface->w > 0 && surface->h > 0) {
|
|
|
+ val.intersect({0, 0, (int32_t)surface->w, (int32_t)surface->h});
|
|
|
+ }
|
|
|
+ if (vport == val) return Result::Success;
|
|
|
+ renderer->viewport(val);
|
|
|
+ vport = val;
|
|
|
+ needRefresh();
|
|
|
+ return Result::Success;
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
#endif /* _TVG_CANVAS_H_ */
|