O2D: Several (unrelated) improvements:

- Use Cairo double-buffering (prevents flickering when there is translucency).
- Add an API to allow JS to indicate the stacking order of layers. (Previously it was the arbitrary order of their creation!)
- Delete layer objects that have been discarded by the JS via Pack::RemoveObject().

TEST=loaded O2D and verified no significant change in perf as a result of double-buffering (~70% of a core before and ~72% of a core after)
BUG=none

Review URL: http://codereview.chromium.org/6320002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71475 0039d316-1c4b-4281-b951-d872f2087c98
parent 07c11a76
......@@ -42,16 +42,26 @@ namespace o2d {
O3D_DEFN_CLASS(Layer, ObjectBase);
Layer::~Layer() {
Renderer* renderer = service_locator()->GetService<Renderer>();
RendererCairo* renderer_cairo = down_cast<RendererCairo*>(renderer);
renderer_cairo->RemoveLayer(this);
}
Layer::Layer(ServiceLocator* service_locator)
: ObjectBase(service_locator),
alpha_(1.0),
x_(0),
y_(0),
z_(0),
width_(0),
height_(0),
scale_x_(1.0),
scale_y_(1.0) {
DLOG(INFO) << "Create Layer";
Renderer* renderer = service_locator->GetService<Renderer>();
RendererCairo* renderer_cairo = down_cast<RendererCairo*>(renderer);
renderer_cairo->AddLayer(this);
}
ObjectBase::Ref Layer::Create(ServiceLocator* service_locator) {
......@@ -61,12 +71,9 @@ ObjectBase::Ref Layer::Create(ServiceLocator* service_locator) {
return ObjectBase::Ref();
}
Layer* image = new Layer(service_locator);
RendererCairo* renderer2d = down_cast<RendererCairo*>(renderer);
renderer2d->AddLayer(image);
Layer* layer = new Layer(service_locator);
return ObjectBase::Ref(image);
return ObjectBase::Ref(layer);
}
} // namespace o2d
......
......@@ -50,6 +50,8 @@ class Layer : public ObjectBase {
public:
typedef SmartPointer<Layer> Ref;
virtual ~Layer();
Pattern* pattern() const {
return pattern_;
}
......@@ -82,6 +84,14 @@ class Layer : public ObjectBase {
y_ = y;
}
double z() const {
return z_;
}
void set_z(double z) {
z_ = z;
}
double width() const {
return width_;
}
......@@ -132,6 +142,9 @@ class Layer : public ObjectBase {
// The y coordinate of the top-left corner of this layer.
double y_;
// The z coordinate of the layer (used only to determine stacking order).
double z_;
// The width of this layer.
double width_;
......
......@@ -72,14 +72,28 @@ void RendererCairo::Destroy() {
display_ = NULL;
}
// Comparison predicate for STL sort.
bool LayerZValueLessThan(const Layer* first, const Layer* second) {
return first->z() < second->z();
}
void RendererCairo::Paint() {
// TODO(tschmelcher): Don't keep creating and destroying the drawing context.
cairo_t* current_drawing = cairo_create(main_surface_);
// Redirect drawing to an off-screen surface (holding only colour information,
// without an alpha channel).
cairo_push_group_with_content(current_drawing, CAIRO_CONTENT_COLOR);
// Sort layers by z value.
// TODO(tschmelcher): Only sort when changes are made.
layer_list_.sort(LayerZValueLessThan);
// Paint the background.
PaintBackground(current_drawing);
// Core process of painting.
for (LayerRefList::iterator i = layer_list_.begin();
for (LayerList::iterator i = layer_list_.begin();
i != layer_list_.end(); i++) {
// Put the state with no mask to the stack.
cairo_save(current_drawing);
......@@ -93,7 +107,7 @@ void RendererCairo::Paint() {
}
// Masking areas for other scene.
LayerRefList::iterator start_mask_it = i;
LayerList::iterator start_mask_it = i;
start_mask_it++;
MaskArea(current_drawing, start_mask_it);
......@@ -109,6 +123,14 @@ void RendererCairo::Paint() {
// Restore to the state with no mask.
cairo_restore(current_drawing);
}
// Finish off-screen drawing and make the off-screen surface the source for
// paints to the screen.
cairo_pop_group_to_source(current_drawing);
// Paint the off-screen surface to the screen.
cairo_paint(current_drawing);
cairo_destroy(current_drawing);
}
......@@ -122,10 +144,10 @@ void RendererCairo::PaintBackground(cairo_t* cr) {
cairo_restore(cr);
}
void RendererCairo::MaskArea(cairo_t* cr, LayerRefList::iterator it) {
void RendererCairo::MaskArea(cairo_t* cr, LayerList::iterator it) {
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
for (LayerRefList::iterator i = it; i != layer_list_.end(); i++) {
for (LayerList::iterator i = it; i != layer_list_.end(); i++) {
// Preparing and updating the Layer.
Layer* cur_mask = *i;
......@@ -140,7 +162,11 @@ void RendererCairo::MaskArea(cairo_t* cr, LayerRefList::iterator it) {
}
void RendererCairo::AddLayer(Layer* image) {
layer_list_.push_front(Layer::Ref(image));
layer_list_.push_front(image);
}
void RendererCairo::RemoveLayer(Layer* image) {
layer_list_.remove(image);
}
void RendererCairo::InitCommon() {
......@@ -213,12 +239,6 @@ void RendererCairo::PlatformSpecificPresent() {
// Don't need to do anything.
}
// TODO(fransiskusx): DO need to implement before shipped.
// Removes the Layer from the array.
void RendererCairo::RemoveLayer(Layer* image) {
NOTIMPLEMENTED();
}
// TODO(fransiskusx): DO need to implement before shipped.
// Get a single fullscreen display mode by id.
// Returns true on success, false on error.
......
......@@ -152,7 +152,7 @@ class RendererCairo : public Renderer {
void PopRenderStates();
protected:
typedef std::list<Layer::Ref> LayerRefList;
typedef std::list<Layer*> LayerList;
// Keep the constructor protected so only factory methods can create
// renderers.
......@@ -219,7 +219,7 @@ class RendererCairo : public Renderer {
float max_z);
// Mask the area of the current layer that will collide with other images.
void MaskArea(cairo_t* cr, LayerRefList::iterator it);
void MaskArea(cairo_t* cr, LayerList::iterator it);
// Paint the background with black color.
// TODO(fransiskusx): Support changing the background color.
......@@ -237,7 +237,7 @@ class RendererCairo : public Renderer {
cairo_t* bg_drawing_;
// Array of Layer
LayerRefList layer_list_;
LayerList layer_list_;
};
} // namespace o2d
......
......@@ -58,6 +58,11 @@ namespace o2d {
%]
[getter, setter] double y;
%[
The z coordinate of the layer (used only to determine stacking order).
%]
[getter, setter] double z;
%[
The width of this layer.
%]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment