diff --git a/src/db/dbCell.cc b/src/db/dbCell.cc index bc87d01bf..ff2ada654 100644 --- a/src/db/dbCell.cc +++ b/src/db/dbCell.cc @@ -27,6 +27,8 @@ #include "dbBox.h" #include "dbPCellVariant.h" +#include + namespace db { @@ -176,7 +178,7 @@ Cell::clear (unsigned int index) { shapes_map::iterator s = m_shapes_map.find(index); if (s != m_shapes_map.end() && ! s->second.empty ()) { - mp_layout->invalidate_bboxes (); // HINT: must come before the change is done! + mp_layout->invalidate_bboxes (index); // HINT: must come before the change is done! s->second.clear (); m_bbox_needs_update = true; } @@ -210,10 +212,21 @@ Cell::shapes (unsigned int index) const } } -void +unsigned int +Cell::index_of_shapes (const Cell::shapes_type *shapes) const +{ + for (shapes_map::const_iterator s = m_shapes_map.begin (); s != m_shapes_map.end (); ++s) { + if (&s->second == shapes) { + return s->first; + } + } + return std::numeric_limits::max (); +} + +void Cell::clear_shapes () { - mp_layout->invalidate_bboxes (); // HINT: must come before the change is done! + mp_layout->invalidate_bboxes (std::numeric_limits::max ()); // HINT: must come before the change is done! clear_shapes_no_invalidate (); } @@ -534,7 +547,7 @@ void Cell::invalidate_insts () { mp_layout->invalidate_hier (); // HINT: must come before the change is done! - mp_layout->invalidate_bboxes (); + mp_layout->invalidate_bboxes (std::numeric_limits::max ()); m_bbox_needs_update = true; } diff --git a/src/db/dbCell.h b/src/db/dbCell.h index 45a1f54e9..00b6683b0 100644 --- a/src/db/dbCell.h +++ b/src/db/dbCell.h @@ -150,6 +150,16 @@ public: */ const shapes_type &shapes (unsigned int index) const; + /** + * @brief Gets the index of a given shapes array + * + * If the shapes container is not part of the cell, std::numeric_limits::max () + * is returned. + * + * This is not a cheap operation. + */ + unsigned int index_of_shapes (const shapes_type *shapes) const; + /** * @brief Clear all shapes in the cell */ diff --git a/src/db/dbLayoutStateModel.cc b/src/db/dbLayoutStateModel.cc index 29588556b..ff02ebbd7 100644 --- a/src/db/dbLayoutStateModel.cc +++ b/src/db/dbLayoutStateModel.cc @@ -59,9 +59,10 @@ LayoutStateModel::do_invalidate_hier () } void -LayoutStateModel::do_invalidate_bboxes () +LayoutStateModel::do_invalidate_bboxes (unsigned int index) { - bboxes_changed_event (); + bboxes_changed_event (index); + bboxes_changed_any_event (); } } diff --git a/src/db/dbLayoutStateModel.h b/src/db/dbLayoutStateModel.h index 709500857..3eea4cf7c 100644 --- a/src/db/dbLayoutStateModel.h +++ b/src/db/dbLayoutStateModel.h @@ -96,11 +96,14 @@ public: * * This method is supposed to be called by shape containers for example if * some event has occured that changed the bounding boxes. + * + * If the index is std::numeric_limits::max, this method + * applies to all layers. */ - void invalidate_bboxes () + void invalidate_bboxes (unsigned int index) { if (! m_bboxes_dirty || m_busy) { - do_invalidate_bboxes (); // must be called before the bboxes are invalidated (stopping of redraw thread requires this) + do_invalidate_bboxes (index); // must be called before the bboxes are invalidated (stopping of redraw thread requires this) m_bboxes_dirty = true; } } @@ -199,7 +202,8 @@ protected: public: tl::Event hier_changed_event; - tl::Event bboxes_changed_event; + tl::event bboxes_changed_event; + tl::Event bboxes_changed_any_event; tl::Event dbu_changed_event; tl::Event cell_name_changed_event; tl::Event prop_ids_changed_event; @@ -211,7 +215,7 @@ private: bool m_busy; void do_invalidate_hier (); - void do_invalidate_bboxes (); + void do_invalidate_bboxes (unsigned int index); }; } diff --git a/src/db/dbShapes.cc b/src/db/dbShapes.cc index 20af0fe5f..2acdae308 100644 --- a/src/db/dbShapes.cc +++ b/src/db/dbShapes.cc @@ -29,6 +29,8 @@ #include "dbUserObject.h" #include "dbLayout.h" +#include + namespace db { @@ -191,8 +193,11 @@ Shapes::invalidate_state () { if (! is_dirty ()) { set_dirty (true); - if (layout ()) { - layout ()->invalidate_bboxes (); + if (layout () && cell ()) { + unsigned int index = cell ()->index_of_shapes (this); + if (index != std::numeric_limits::max ()) { + layout ()->invalidate_bboxes (index); + } } } } @@ -852,12 +857,14 @@ Shapes::replace (const Shapes::shape_type &ref, const Sh &sh) void Shapes::clear () { - for (tl::vector::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) { - (*l)->clear (this, manager ()); - delete *l; + if (!m_layers.empty ()) { + for (tl::vector::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) { + (*l)->clear (this, manager ()); + delete *l; + } + invalidate_state (); // HINT: must come before the change is done! + m_layers.clear (); } - invalidate_state (); // HINT: must come before the change is done! - m_layers.clear (); } void Shapes::update_bbox () diff --git a/src/lay/laySearchReplaceDialog.cc b/src/lay/laySearchReplaceDialog.cc index a76f90b6a..6b8ba04bc 100644 --- a/src/lay/laySearchReplaceDialog.cc +++ b/src/lay/laySearchReplaceDialog.cc @@ -1397,7 +1397,7 @@ void SearchReplaceDialog::attach_layout (db::Layout *layout) { layout->hier_changed_event.add (this, &SearchReplaceDialog::layout_changed); - layout->bboxes_changed_event.add (this, &SearchReplaceDialog::layout_changed); + layout->bboxes_changed_any_event.add (this, &SearchReplaceDialog::layout_changed); layout->cell_name_changed_event.add (this, &SearchReplaceDialog::layout_changed); layout->layer_properties_changed_event.add (this, &SearchReplaceDialog::layout_changed); } diff --git a/src/laybasic/layAnnotationShapes.h b/src/laybasic/layAnnotationShapes.h index 43a30e281..ca9ac9936 100644 --- a/src/laybasic/layAnnotationShapes.h +++ b/src/laybasic/layAnnotationShapes.h @@ -32,6 +32,7 @@ #include "dbLayoutStateModel.h" #include +#include namespace lay { @@ -351,7 +352,7 @@ public: private: void invalidate_state () { - invalidate_bboxes (); + invalidate_bboxes (std::numeric_limits::max ()); } virtual void do_update (); diff --git a/src/laybasic/layCellView.cc b/src/laybasic/layCellView.cc index f77825b81..3b8aeee89 100644 --- a/src/laybasic/layCellView.cc +++ b/src/laybasic/layCellView.cc @@ -79,7 +79,7 @@ LayoutHandle::LayoutHandle (db::Layout *layout, const std::string &filename) } mp_layout->hier_changed_event.add (this, &LayoutHandle::layout_changed); - mp_layout->bboxes_changed_event.add (this, &LayoutHandle::layout_changed); + mp_layout->bboxes_changed_any_event.add (this, &LayoutHandle::layout_changed); mp_layout->cell_name_changed_event.add (this, &LayoutHandle::layout_changed); mp_layout->prop_ids_changed_event.add (this, &LayoutHandle::layout_changed); mp_layout->layer_properties_changed_event.add (this, &LayoutHandle::layout_changed); diff --git a/src/laybasic/layLayoutView.cc b/src/laybasic/layLayoutView.cc index 7d574de6d..8e83c2c86 100644 --- a/src/laybasic/layLayoutView.cc +++ b/src/laybasic/layLayoutView.cc @@ -645,7 +645,7 @@ void LayoutView::update_event_handlers () for (unsigned int i = 0; i < cellviews (); ++i) { cellview (i)->layout ().hier_changed_event.add (this, &LayoutView::signal_hier_changed); - cellview (i)->layout ().bboxes_changed_event.add (this, &LayoutView::signal_bboxes_changed); + cellview (i)->layout ().bboxes_changed_event.add (this, &LayoutView::signal_bboxes_from_layer_changed, i); cellview (i)->layout ().dbu_changed_event.add (this, &LayoutView::signal_bboxes_changed); cellview (i)->layout ().prop_ids_changed_event.add (this, &LayoutView::signal_prop_ids_changed); cellview (i)->layout ().layer_properties_changed_event.add (this, &LayoutView::signal_layer_properties_changed); @@ -653,7 +653,7 @@ void LayoutView::update_event_handlers () cellview (i)->apply_technology_with_sender_event.add (this, &LayoutView::signal_apply_technology); } - annotation_shapes ().bboxes_changed_event.add (this, &LayoutView::signal_annotations_changed); + annotation_shapes ().bboxes_changed_any_event.add (this, &LayoutView::signal_annotations_changed); mp_canvas->viewport_changed_event.add (this, &LayoutView::viewport_changed); } @@ -2066,15 +2066,35 @@ LayoutView::signal_hier_changed () hier_changed_event (); } +void +LayoutView::signal_bboxes_from_layer_changed (unsigned int cv_index, unsigned int layer_index) +{ + if (layer_index == std::numeric_limits::max ()) { + + // redraw all + signal_bboxes_changed (); + + } else { + + // redraw only the layers required for redrawing + for (std::vector::const_iterator l = mp_canvas->get_redraw_layers ().begin (); l != mp_canvas->get_redraw_layers ().end (); ++l) { + if (l->cellview_index == int (cv_index) && (layer_index == std::numeric_limits::max () || l->layer_index == int (layer_index))) { + redraw_layer ((unsigned int) (l - mp_canvas->get_redraw_layers ().begin ())); + } + } + + // forward this event to our observers + geom_changed_event (); + + } +} + void LayoutView::signal_bboxes_changed () { // schedule a redraw request for all layers - // HINT: it could be optimized if we knew which layer to redraw. However, this - // is somewhat difficult to find out: first, we had to identify the layer we need to - // redraw, the the layout which to redraw and then the layer views which need to be - // redrawn .. redraw (); + // forward this event to our observers geom_changed_event (); } diff --git a/src/laybasic/layLayoutView.h b/src/laybasic/layLayoutView.h index d47332a46..7748c1c2c 100644 --- a/src/laybasic/layLayoutView.h +++ b/src/laybasic/layLayoutView.h @@ -2494,6 +2494,7 @@ public slots: // event handlers used to connect to the layout object's events void signal_hier_changed (); + void signal_bboxes_from_layer_changed (unsigned int cv_index, unsigned int layer_index); void signal_bboxes_changed (); void signal_prop_ids_changed (); void signal_layer_properties_changed (); diff --git a/src/laybasic/layRedrawThread.cc b/src/laybasic/layRedrawThread.cc index 28721f9b5..fb4c34024 100644 --- a/src/laybasic/layRedrawThread.cc +++ b/src/laybasic/layRedrawThread.cc @@ -193,6 +193,7 @@ RedrawThread::restart (const std::vector &restart) { m_redraw_regions.clear (); m_redraw_regions.push_back (db::Box (db::Point (0, 0), db::Point (m_width, m_height))); + m_valid_region = m_stored_region = db::DBox (); do_start (false, 0, 0, restart, -1); } @@ -241,13 +242,13 @@ RedrawThread::do_start (bool clear, const db::Vector *shift_vector, const std::v cv->layout ().update (); // attach to the layout object to receive change notifications to stop the redraw thread cv->layout ().hier_changed_event.add (this, &RedrawThread::layout_changed); - cv->layout ().bboxes_changed_event.add (this, &RedrawThread::layout_changed); + cv->layout ().bboxes_changed_any_event.add (this, &RedrawThread::layout_changed); } } mp_view->annotation_shapes ().update (); // attach to the layout object to receive change notifications to stop the redraw thread mp_view->annotation_shapes ().hier_changed_event.add (this, &RedrawThread::layout_changed); // not really required, since the shapes have no hierarchy, but for completeness .. - mp_view->annotation_shapes ().bboxes_changed_event.add (this, &RedrawThread::layout_changed); + mp_view->annotation_shapes ().bboxes_changed_any_event.add (this, &RedrawThread::layout_changed); mp_view->cellviews_about_to_change_event.add (this, &RedrawThread::layout_changed); mp_view->cellview_about_to_change_event.add (this, &RedrawThread::layout_changed_with_int); @@ -275,8 +276,10 @@ RedrawThread::do_start (bool clear, const db::Vector *shift_vector, const std::v if (*l == draw_custom_queue_entry) { planes_to_init.push_back (-1); } else if (*l >= 0 && *l < int (m_layers.size ())) { - for (int o = 0; o < planes_per_layer; ++o) { - planes_to_init.push_back (o + *l * planes_per_layer + special_planes_before + special_planes_after); + for (int i = 0; i < planes_per_layer / 3; ++i) { + planes_to_init.push_back (*l * (planes_per_layer / 3) + special_planes_before + i); + planes_to_init.push_back ((*l + m_nlayers) * (planes_per_layer / 3) + special_planes_before + i); + planes_to_init.push_back ((*l + m_nlayers * 2) * (planes_per_layer / 3) + special_planes_before + i); } } }