diff options
author | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-14 20:03:45 +0000 |
---|---|---|
committer | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-14 20:03:45 +0000 |
commit | 645811527a8062d2db4bdd3e93111f55af4cc3c7 (patch) | |
tree | 32abbb32bbdca53a2dadca2ba86c0ca2234a281c | |
parent | 07c11a7688f9677967eae04b237c38c6166420c1 (diff) | |
download | chromium_src-645811527a8062d2db4bdd3e93111f55af4cc3c7.zip chromium_src-645811527a8062d2db4bdd3e93111f55af4cc3c7.tar.gz chromium_src-645811527a8062d2db4bdd3e93111f55af4cc3c7.tar.bz2 |
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
-rw-r--r-- | o3d/core/cross/cairo/layer.cc | 17 | ||||
-rw-r--r-- | o3d/core/cross/cairo/layer.h | 13 | ||||
-rw-r--r-- | o3d/core/cross/cairo/renderer_cairo.cc | 42 | ||||
-rw-r--r-- | o3d/core/cross/cairo/renderer_cairo.h | 6 | ||||
-rw-r--r-- | o3d/plugin/idl/layer.idl | 5 |
5 files changed, 64 insertions, 19 deletions
diff --git a/o3d/core/cross/cairo/layer.cc b/o3d/core/cross/cairo/layer.cc index 3d536f0..7317dc1 100644 --- a/o3d/core/cross/cairo/layer.cc +++ b/o3d/core/cross/cairo/layer.cc @@ -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 diff --git a/o3d/core/cross/cairo/layer.h b/o3d/core/cross/cairo/layer.h index 6408dc0..8e81206 100644 --- a/o3d/core/cross/cairo/layer.h +++ b/o3d/core/cross/cairo/layer.h @@ -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_; diff --git a/o3d/core/cross/cairo/renderer_cairo.cc b/o3d/core/cross/cairo/renderer_cairo.cc index 8bd698a..1cdc7e1 100644 --- a/o3d/core/cross/cairo/renderer_cairo.cc +++ b/o3d/core/cross/cairo/renderer_cairo.cc @@ -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() { @@ -214,12 +240,6 @@ void RendererCairo::PlatformSpecificPresent() { } // 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. bool RendererCairo::GetDisplayMode(int id, DisplayMode* mode) { diff --git a/o3d/core/cross/cairo/renderer_cairo.h b/o3d/core/cross/cairo/renderer_cairo.h index f62698a..e985dc1 100644 --- a/o3d/core/cross/cairo/renderer_cairo.h +++ b/o3d/core/cross/cairo/renderer_cairo.h @@ -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 diff --git a/o3d/plugin/idl/layer.idl b/o3d/plugin/idl/layer.idl index 964feaf..3a479ba 100644 --- a/o3d/plugin/idl/layer.idl +++ b/o3d/plugin/idl/layer.idl @@ -59,6 +59,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. %] [getter, setter] double width; |