mirror of https://github.com/KLayout/klayout.git
Drawing optimization: only redraw changed layers
The effect was: when drawing a shape on a single layer, all layers have been redrawn. This was changed such that only the affected layer is actually redrawn.
This commit is contained in:
parent
83f12382e8
commit
55bac69a4a
|
|
@ -27,6 +27,8 @@
|
||||||
#include "dbBox.h"
|
#include "dbBox.h"
|
||||||
#include "dbPCellVariant.h"
|
#include "dbPCellVariant.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -176,7 +178,7 @@ Cell::clear (unsigned int index)
|
||||||
{
|
{
|
||||||
shapes_map::iterator s = m_shapes_map.find(index);
|
shapes_map::iterator s = m_shapes_map.find(index);
|
||||||
if (s != m_shapes_map.end() && ! s->second.empty ()) {
|
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 ();
|
s->second.clear ();
|
||||||
m_bbox_needs_update = true;
|
m_bbox_needs_update = true;
|
||||||
}
|
}
|
||||||
|
|
@ -210,10 +212,21 @@ Cell::shapes (unsigned int index) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<unsigned int>::max ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Cell::clear_shapes ()
|
Cell::clear_shapes ()
|
||||||
{
|
{
|
||||||
mp_layout->invalidate_bboxes (); // HINT: must come before the change is done!
|
mp_layout->invalidate_bboxes (std::numeric_limits<unsigned int>::max ()); // HINT: must come before the change is done!
|
||||||
clear_shapes_no_invalidate ();
|
clear_shapes_no_invalidate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -534,7 +547,7 @@ void
|
||||||
Cell::invalidate_insts ()
|
Cell::invalidate_insts ()
|
||||||
{
|
{
|
||||||
mp_layout->invalidate_hier (); // HINT: must come before the change is done!
|
mp_layout->invalidate_hier (); // HINT: must come before the change is done!
|
||||||
mp_layout->invalidate_bboxes ();
|
mp_layout->invalidate_bboxes (std::numeric_limits<unsigned int>::max ());
|
||||||
m_bbox_needs_update = true;
|
m_bbox_needs_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,16 @@ public:
|
||||||
*/
|
*/
|
||||||
const shapes_type &shapes (unsigned int index) const;
|
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<unsigned int>::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
|
* @brief Clear all shapes in the cell
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,10 @@ LayoutStateModel::do_invalidate_hier ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LayoutStateModel::do_invalidate_bboxes ()
|
LayoutStateModel::do_invalidate_bboxes (unsigned int index)
|
||||||
{
|
{
|
||||||
bboxes_changed_event ();
|
bboxes_changed_event (index);
|
||||||
|
bboxes_changed_any_event ();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,11 +96,14 @@ public:
|
||||||
*
|
*
|
||||||
* This method is supposed to be called by shape containers for example if
|
* This method is supposed to be called by shape containers for example if
|
||||||
* some event has occured that changed the bounding boxes.
|
* some event has occured that changed the bounding boxes.
|
||||||
|
*
|
||||||
|
* If the index is std::numeric_limits<unsigned int>::max, this method
|
||||||
|
* applies to all layers.
|
||||||
*/
|
*/
|
||||||
void invalidate_bboxes ()
|
void invalidate_bboxes (unsigned int index)
|
||||||
{
|
{
|
||||||
if (! m_bboxes_dirty || m_busy) {
|
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;
|
m_bboxes_dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +202,8 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
tl::Event hier_changed_event;
|
tl::Event hier_changed_event;
|
||||||
tl::Event bboxes_changed_event;
|
tl::event<unsigned int> bboxes_changed_event;
|
||||||
|
tl::Event bboxes_changed_any_event;
|
||||||
tl::Event dbu_changed_event;
|
tl::Event dbu_changed_event;
|
||||||
tl::Event cell_name_changed_event;
|
tl::Event cell_name_changed_event;
|
||||||
tl::Event prop_ids_changed_event;
|
tl::Event prop_ids_changed_event;
|
||||||
|
|
@ -211,7 +215,7 @@ private:
|
||||||
bool m_busy;
|
bool m_busy;
|
||||||
|
|
||||||
void do_invalidate_hier ();
|
void do_invalidate_hier ();
|
||||||
void do_invalidate_bboxes ();
|
void do_invalidate_bboxes (unsigned int index);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
#include "dbUserObject.h"
|
#include "dbUserObject.h"
|
||||||
#include "dbLayout.h"
|
#include "dbLayout.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -191,8 +193,11 @@ Shapes::invalidate_state ()
|
||||||
{
|
{
|
||||||
if (! is_dirty ()) {
|
if (! is_dirty ()) {
|
||||||
set_dirty (true);
|
set_dirty (true);
|
||||||
if (layout ()) {
|
if (layout () && cell ()) {
|
||||||
layout ()->invalidate_bboxes ();
|
unsigned int index = cell ()->index_of_shapes (this);
|
||||||
|
if (index != std::numeric_limits<unsigned int>::max ()) {
|
||||||
|
layout ()->invalidate_bboxes (index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -852,6 +857,7 @@ Shapes::replace (const Shapes::shape_type &ref, const Sh &sh)
|
||||||
void
|
void
|
||||||
Shapes::clear ()
|
Shapes::clear ()
|
||||||
{
|
{
|
||||||
|
if (!m_layers.empty ()) {
|
||||||
for (tl::vector<LayerBase *>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
for (tl::vector<LayerBase *>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
||||||
(*l)->clear (this, manager ());
|
(*l)->clear (this, manager ());
|
||||||
delete *l;
|
delete *l;
|
||||||
|
|
@ -859,6 +865,7 @@ Shapes::clear ()
|
||||||
invalidate_state (); // HINT: must come before the change is done!
|
invalidate_state (); // HINT: must come before the change is done!
|
||||||
m_layers.clear ();
|
m_layers.clear ();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Shapes::update_bbox ()
|
void Shapes::update_bbox ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1397,7 +1397,7 @@ void
|
||||||
SearchReplaceDialog::attach_layout (db::Layout *layout)
|
SearchReplaceDialog::attach_layout (db::Layout *layout)
|
||||||
{
|
{
|
||||||
layout->hier_changed_event.add (this, &SearchReplaceDialog::layout_changed);
|
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->cell_name_changed_event.add (this, &SearchReplaceDialog::layout_changed);
|
||||||
layout->layer_properties_changed_event.add (this, &SearchReplaceDialog::layout_changed);
|
layout->layer_properties_changed_event.add (this, &SearchReplaceDialog::layout_changed);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "dbLayoutStateModel.h"
|
#include "dbLayoutStateModel.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace lay
|
namespace lay
|
||||||
{
|
{
|
||||||
|
|
@ -351,7 +352,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void invalidate_state ()
|
void invalidate_state ()
|
||||||
{
|
{
|
||||||
invalidate_bboxes ();
|
invalidate_bboxes (std::numeric_limits<unsigned int>::max ());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void do_update ();
|
virtual void do_update ();
|
||||||
|
|
|
||||||
|
|
@ -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->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->cell_name_changed_event.add (this, &LayoutHandle::layout_changed);
|
||||||
mp_layout->prop_ids_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);
|
mp_layout->layer_properties_changed_event.add (this, &LayoutHandle::layout_changed);
|
||||||
|
|
|
||||||
|
|
@ -645,7 +645,7 @@ void LayoutView::update_event_handlers ()
|
||||||
|
|
||||||
for (unsigned int i = 0; i < cellviews (); ++i) {
|
for (unsigned int i = 0; i < cellviews (); ++i) {
|
||||||
cellview (i)->layout ().hier_changed_event.add (this, &LayoutView::signal_hier_changed);
|
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 ().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 ().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);
|
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);
|
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);
|
mp_canvas->viewport_changed_event.add (this, &LayoutView::viewport_changed);
|
||||||
}
|
}
|
||||||
|
|
@ -2066,15 +2066,35 @@ LayoutView::signal_hier_changed ()
|
||||||
hier_changed_event ();
|
hier_changed_event ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LayoutView::signal_bboxes_from_layer_changed (unsigned int cv_index, unsigned int layer_index)
|
||||||
|
{
|
||||||
|
if (layer_index == std::numeric_limits<unsigned int>::max ()) {
|
||||||
|
|
||||||
|
// redraw all
|
||||||
|
signal_bboxes_changed ();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// redraw only the layers required for redrawing
|
||||||
|
for (std::vector<lay::RedrawLayerInfo>::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<unsigned int>::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
|
void
|
||||||
LayoutView::signal_bboxes_changed ()
|
LayoutView::signal_bboxes_changed ()
|
||||||
{
|
{
|
||||||
// schedule a redraw request for all layers
|
// 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 ();
|
redraw ();
|
||||||
|
|
||||||
// forward this event to our observers
|
// forward this event to our observers
|
||||||
geom_changed_event ();
|
geom_changed_event ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2494,6 +2494,7 @@ public slots:
|
||||||
|
|
||||||
// event handlers used to connect to the layout object's events
|
// event handlers used to connect to the layout object's events
|
||||||
void signal_hier_changed ();
|
void signal_hier_changed ();
|
||||||
|
void signal_bboxes_from_layer_changed (unsigned int cv_index, unsigned int layer_index);
|
||||||
void signal_bboxes_changed ();
|
void signal_bboxes_changed ();
|
||||||
void signal_prop_ids_changed ();
|
void signal_prop_ids_changed ();
|
||||||
void signal_layer_properties_changed ();
|
void signal_layer_properties_changed ();
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,7 @@ RedrawThread::restart (const std::vector<int> &restart)
|
||||||
{
|
{
|
||||||
m_redraw_regions.clear ();
|
m_redraw_regions.clear ();
|
||||||
m_redraw_regions.push_back (db::Box (db::Point (0, 0), db::Point (m_width, m_height)));
|
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);
|
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 ();
|
cv->layout ().update ();
|
||||||
// attach to the layout object to receive change notifications to stop the redraw thread
|
// 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 ().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 ();
|
mp_view->annotation_shapes ().update ();
|
||||||
// attach to the layout object to receive change notifications to stop the redraw thread
|
// 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 ().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->cellviews_about_to_change_event.add (this, &RedrawThread::layout_changed);
|
||||||
mp_view->cellview_about_to_change_event.add (this, &RedrawThread::layout_changed_with_int);
|
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) {
|
if (*l == draw_custom_queue_entry) {
|
||||||
planes_to_init.push_back (-1);
|
planes_to_init.push_back (-1);
|
||||||
} else if (*l >= 0 && *l < int (m_layers.size ())) {
|
} else if (*l >= 0 && *l < int (m_layers.size ())) {
|
||||||
for (int o = 0; o < planes_per_layer; ++o) {
|
for (int i = 0; i < planes_per_layer / 3; ++i) {
|
||||||
planes_to_init.push_back (o + *l * planes_per_layer + special_planes_before + special_planes_after);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue