From a0d05753ade53866a926718061add19aff1595e1 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 28 Dec 2020 00:09:27 +0100 Subject: [PATCH 1/3] No segfault on OpenGL initialization failure but nice error screen. --- .../tools/view_25d/lay_plugin/D25View.ui | 79 ++++++++++++++++++- .../tools/view_25d/lay_plugin/layD25View.cc | 10 +++ .../tools/view_25d/lay_plugin/layD25View.h | 1 + .../view_25d/lay_plugin/layD25ViewWidget.cc | 50 ++++++++++-- .../view_25d/lay_plugin/layD25ViewWidget.h | 10 +++ 5 files changed, 144 insertions(+), 6 deletions(-) diff --git a/src/plugins/tools/view_25d/lay_plugin/D25View.ui b/src/plugins/tools/view_25d/lay_plugin/D25View.ui index f09a1a654..5e509de09 100644 --- a/src/plugins/tools/view_25d/lay_plugin/D25View.ui +++ b/src/plugins/tools/view_25d/lay_plugin/D25View.ui @@ -243,7 +243,84 @@ - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 255 + 213 + 213 + + + + + + + + + 255 + 213 + 213 + + + + + + + + + 239 + 239 + 239 + + + + + + + + + + + diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25View.cc b/src/plugins/tools/view_25d/lay_plugin/layD25View.cc index fd8d57bac..508eb89c5 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25View.cc +++ b/src/plugins/tools/view_25d/lay_plugin/layD25View.cc @@ -50,6 +50,9 @@ D25View::D25View (QWidget *parent) connect (mp_ui->fit_bottom, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ())); connect (mp_ui->zoom_slider, SIGNAL (valueChanged (int)), this, SLOT (scale_slider_changed (int))); connect (mp_ui->d25_view, SIGNAL (scale_factor_changed (double)), this, SLOT (scale_factor_changed (double))); + connect (mp_ui->d25_view, SIGNAL (init_failed ()), this, SLOT (init_failed ())); + + mp_ui->gl_stack->setCurrentIndex (0); } D25View::~D25View () @@ -65,6 +68,13 @@ static QString scale_factor_to_string (double f) return s; } +void +D25View::init_failed () +{ + mp_ui->error_text->setPlainText (tl::to_qstring (mp_ui->d25_view->error ())); + mp_ui->gl_stack->setCurrentIndex (1); +} + void D25View::scale_slider_changed (int value) { diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25View.h b/src/plugins/tools/view_25d/lay_plugin/layD25View.h index 6f776ed3c..0ac98ebe1 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25View.h +++ b/src/plugins/tools/view_25d/lay_plugin/layD25View.h @@ -58,6 +58,7 @@ private slots: void fit_button_clicked (); void scale_factor_changed (double f); void scale_slider_changed (int value); + void init_failed (); private: Ui::D25View *mp_ui; diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc index ff9fc8f2a..58faad65c 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc +++ b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include "math.h" @@ -186,7 +189,7 @@ private: D25ViewWidget::D25ViewWidget (QWidget *parent) : QOpenGLWidget (parent), - m_shapes_program (0) + m_shapes_program (0), m_gridplane_program (0) { QSurfaceFormat format; format.setDepthBufferSize (24); @@ -694,6 +697,39 @@ static std::pair find_grid (double v) void D25ViewWidget::initializeGL () +{ + tl_assert (m_shapes_program == 0); + tl_assert (m_gridplane_program == 0); + + bool error = false; + + try { + do_initialize_gl (); + } catch (tl::Exception &ex) { + m_error = ex.msg (); + error = true; + } catch (std::exception &ex) { + m_error = ex.what (); + error = true; + } catch (...) { + m_error = "(unspecific error)"; + error = true; + } + + if (error) { + + delete m_shapes_program; + m_shapes_program = 0; + delete m_gridplane_program; + m_gridplane_program = 0; + + emit init_failed (); + + } +} + +void +D25ViewWidget::do_initialize_gl () { QOpenGLFunctions::initializeOpenGLFunctions(); @@ -824,8 +860,8 @@ D25ViewWidget::initializeGL () void D25ViewWidget::paintGL () { - const qreal retinaScale = devicePixelRatio (); - glViewport (0, 0, width () * retinaScale, height () * retinaScale); + const qreal retina_scale = devicePixelRatio (); + glViewport (0, 0, width () * retina_scale, height () * retina_scale); QColor c = mp_view->background_color (); float foreground_rgb = (c.green () > 128 ? 0.0f : 1.0f); @@ -835,6 +871,12 @@ D25ViewWidget::paintGL () glClearColor (float (c.red ()) / 255.0f, float (c.green ()) / 255.0f, float (c.blue ()) / 255.0f, 1.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + const int positions = 0; + + if (! m_shapes_program || ! m_gridplane_program) { + return; + } + QMatrix4x4 scene_trans, scene_trans_wo_y; // provide the displacement and scaling (in this order!) @@ -846,8 +888,6 @@ D25ViewWidget::paintGL () scene_trans_wo_y = scene_trans; scene_trans_wo_y.translate (QVector3D (0.0, -m_displacement.y (), 0.0)); - const int positions = 0; - m_shapes_program->bind (); // draw the actual layout diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.h b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.h index e23b068a5..700e41079 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.h +++ b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.h @@ -104,8 +104,14 @@ public: refresh (); } + const std::string &error () const + { + return m_error; + } + signals: void scale_factor_changed (double f); + void init_failed (); protected: virtual void camera_changed (); @@ -119,6 +125,7 @@ private: std::auto_ptr mp_mode; QOpenGLShaderProgram *m_shapes_program, *m_gridplane_program; + std::string m_error; double m_scale_factor; QVector3D m_displacement; lay::LayoutView *mp_view; @@ -126,9 +133,11 @@ private: double m_zmin, m_zmax; std::list m_vertex_chunks; + std::list m_normals_chunks; struct LayerInfo { const chunks_type *vertex_chunk; + const chunks_type *normals_chunk; GLfloat color [4]; }; @@ -138,6 +147,7 @@ private: void paintGL (); void resizeGL (int w, int h); + void do_initialize_gl (); bool prepare_view(); void render_layout (D25ViewWidget::chunks_type &chunks, const db::Layout &layout, const db::Cell &cell, unsigned int layer, double zstart, double zstop); void render_polygon (D25ViewWidget::chunks_type &chunks, const db::Polygon &poly, double dbu, double zstart, double zstop); From cd73987b30e2a441ddd5be51ff296849e188271c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 28 Dec 2020 21:13:07 +0100 Subject: [PATCH 2/3] More consistent behavior of the preset views (front, top ...) --- src/plugins/tools/view_25d/lay_plugin/layD25View.cc | 6 ++++-- src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25View.cc b/src/plugins/tools/view_25d/lay_plugin/layD25View.cc index 508eb89c5..ae7aec5da 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25View.cc +++ b/src/plugins/tools/view_25d/lay_plugin/layD25View.cc @@ -31,7 +31,7 @@ namespace lay { -const double initial_elevation = 3.0; +const double initial_elevation = 15.0; D25View::D25View (QWidget *parent) : QDialog (parent) @@ -110,7 +110,7 @@ D25View::exec_dialog (lay::LayoutView *view) mp_ui->d25_view->reset (); mp_ui->d25_view->set_cam_azimuth (0.0); - mp_ui->d25_view->set_cam_elevation (initial_elevation); + mp_ui->d25_view->set_cam_elevation (-initial_elevation); mp_ui->d25_view->fit (); int ret = QDialog::exec (); @@ -140,8 +140,10 @@ D25View::fit_button_clicked () azimuth = -90.0; elevation = -initial_elevation; } else if (sender () == mp_ui->fit_top) { + azimuth = 0; elevation = -90; } else if (sender () == mp_ui->fit_bottom) { + azimuth = 0; elevation = 90; } diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc index 58faad65c..bd849ba7b 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc +++ b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc @@ -384,9 +384,8 @@ D25ViewWidget::fit () QVector3D new_center (0.0, 0.0, -dv / 2.0 + std::max (0.0, -d / (2.0 * tan (cam_fov () * M_PI / 180.0 / 2.0)) + cam_dist ())); QVector3D new_center_in_scene = cam_trans ().inverted ().map (new_center); - new_center_in_scene.setY (0.0); - m_displacement = (new_center_in_scene - dim * 0.5) / m_scale_factor - bll; + m_displacement.setY (0.0); refresh (); From dd84e64446e96e83a90c0ff1ee8b1447c390e852 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 30 Dec 2020 23:37:01 +0100 Subject: [PATCH 3/3] Fixed an issue with the OASIS reader (unused cells popped up as dummy top levels) This happens when OASIS declares a cell name without actually using it. The intended behavior is to drop such cells. --- src/db/db/dbCommonReader.cc | 11 ++++++ src/db/db/dbCommonReader.h | 1 + ...dbOASISReader.cc => dbOASISReaderTests.cc} | 5 +++ .../streamers/oasis/unit_tests/unit_tests.pro | 2 +- testdata/oasis/mkall.sh | 2 +- testdata/oasis/t2.3.ot | 4 +- testdata/oasis/t2.4.ot | 4 +- testdata/oasis/t2.5.ot | 4 +- testdata/oasis/t2.7.oas | Bin 0 -> 304 bytes testdata/oasis/t2.7.ot | 35 ++++++++++++++++++ testdata/oasis/t2.7_au.txt | 4 ++ 11 files changed, 64 insertions(+), 8 deletions(-) rename src/plugins/streamers/oasis/unit_tests/{dbOASISReader.cc => dbOASISReaderTests.cc} (99%) create mode 100644 testdata/oasis/t2.7.oas create mode 100644 testdata/oasis/t2.7.ot create mode 100644 testdata/oasis/t2.7_au.txt diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc index f52e5cdf2..a2a7b597e 100644 --- a/src/db/db/dbCommonReader.cc +++ b/src/db/db/dbCommonReader.cc @@ -54,6 +54,7 @@ CommonReader::make_cell (db::Layout &layout, const std::string &cn) common_reader_error (tl::sprintf (tl::to_string (tr ("A cell with name %s already exists")), cn)); } + m_temp_cells.erase (cell.cell_index ()); cell.set_ghost_cell (false); return cell.cell_index (); @@ -98,6 +99,7 @@ CommonReader::make_cell (db::Layout &layout, size_t id) common_reader_error (tl::sprintf (tl::to_string (tr ("A cell with ID %ld already exists")), id)); } + m_temp_cells.erase (cell.cell_index ()); cell.set_ghost_cell (false); return cell.cell_index (); @@ -180,6 +182,7 @@ CommonReader::rename_cell (db::Layout &layout, size_t id, const std::string &cn) db::cell_index_type ci = layout.add_anonymous_cell (); layout.cell (ci).set_ghost_cell (true); + m_temp_cells.insert (ci); m_id_map [id] = std::make_pair (cn, ci); m_name_map [cn] = std::make_pair (id, ci); @@ -195,6 +198,7 @@ CommonReader::cell_for_instance (db::Layout &layout, size_t id) std::map >::iterator iid = m_id_map.find (id); if (iid != m_id_map.end ()) { + m_temp_cells.erase (iid->second.second); return iid->second.second; } else { @@ -216,6 +220,7 @@ CommonReader::cell_for_instance (db::Layout &layout, const std::string &cn) std::map >::iterator iname = m_name_map.find (cn); if (iname != m_name_map.end ()) { + m_temp_cells.erase (iname->second.second); return iname->second.second; } else { @@ -423,6 +428,12 @@ CommonReader::finish (db::Layout &layout) } + // remove temporary cells (some that were "declared" by "rename_cell" but not used by cell_for_instance) + + for (std::set::const_iterator ci = m_temp_cells.begin (); ci != m_temp_cells.end (); ++ci) { + layout.delete_cell (*ci); + } + // resolve layer multi-mapping for (std::map, unsigned int>::const_iterator i = m_multi_mapping_placeholders.begin (); i != m_multi_mapping_placeholders.end (); ++i) { diff --git a/src/db/db/dbCommonReader.h b/src/db/db/dbCommonReader.h index 81d361672..0fe3c8081 100644 --- a/src/db/db/dbCommonReader.h +++ b/src/db/db/dbCommonReader.h @@ -251,6 +251,7 @@ protected: private: std::map > m_id_map; std::map > m_name_map; + std::set m_temp_cells; std::map m_name_for_id; CellConflictResolution m_cc_resolution; bool m_create_layers; diff --git a/src/plugins/streamers/oasis/unit_tests/dbOASISReader.cc b/src/plugins/streamers/oasis/unit_tests/dbOASISReaderTests.cc similarity index 99% rename from src/plugins/streamers/oasis/unit_tests/dbOASISReader.cc rename to src/plugins/streamers/oasis/unit_tests/dbOASISReaderTests.cc index 8534e0ab4..836c901f1 100644 --- a/src/plugins/streamers/oasis/unit_tests/dbOASISReader.cc +++ b/src/plugins/streamers/oasis/unit_tests/dbOASISReaderTests.cc @@ -264,6 +264,11 @@ TEST(2_6) run_test (_this, "2.6"); } +TEST(2_7) +{ + run_test (_this, "2.7"); +} + TEST(3_1) { run_test (_this, "3.1"); diff --git a/src/plugins/streamers/oasis/unit_tests/unit_tests.pro b/src/plugins/streamers/oasis/unit_tests/unit_tests.pro index 2532285f9..d5aab7467 100644 --- a/src/plugins/streamers/oasis/unit_tests/unit_tests.pro +++ b/src/plugins/streamers/oasis/unit_tests/unit_tests.pro @@ -6,7 +6,7 @@ TARGET = oasis_tests include($$PWD/../../../../lib_ut.pri) SOURCES = \ - dbOASISReader.cc \ + dbOASISReaderTests.cc \ dbOASISWriter2.cc \ dbOASISWriter.cc \ diff --git a/testdata/oasis/mkall.sh b/testdata/oasis/mkall.sh index 633e4f313..b56d4e137 100755 --- a/testdata/oasis/mkall.sh +++ b/testdata/oasis/mkall.sh @@ -6,6 +6,6 @@ export LANG for t in *.ot; do out=`echo $t | sed 's/.ot$/.oas/'` echo "$t -> $out" - ./mkoasis.tcl $t $out + tclsh ./mkoasis.tcl $t $out done diff --git a/testdata/oasis/t2.3.ot b/testdata/oasis/t2.3.ot index 3ef18cfa8..8b08f014d 100644 --- a/testdata/oasis/t2.3.ot +++ b/testdata/oasis/t2.3.ot @@ -14,12 +14,12 @@ header uint 0 ;# offset table is in start record for { set i 0 } { $i < 12 } { incr i } { uint 0 } -# XYZ gets assigned 1 +# ABC gets assigned 1 record CELLNAME_ID str ABC uint 1 -# ABC gets assigned 0 implicitly +# XYZ gets assigned 0 implicitly record CELLNAME str XYZ ;# FAIL: implicit and explicit assignment may not be mixed diff --git a/testdata/oasis/t2.4.ot b/testdata/oasis/t2.4.ot index d1def8758..a8848fea0 100644 --- a/testdata/oasis/t2.4.ot +++ b/testdata/oasis/t2.4.ot @@ -20,12 +20,12 @@ header uint 0 ;# offset table is in start record for { set i 0 } { $i < 12 } { incr i } { uint 0 } -# XYZ gets assigned 1 +# ABC gets assigned 1 record CELLNAME_ID str ABC uint 1 -# ABC gets assigned 0 +# XYZ gets assigned 0 record CELLNAME_ID str XYZ uint 0 diff --git a/testdata/oasis/t2.5.ot b/testdata/oasis/t2.5.ot index 055f73530..e9b789051 100644 --- a/testdata/oasis/t2.5.ot +++ b/testdata/oasis/t2.5.ot @@ -14,12 +14,12 @@ header uint 0 ;# offset table is in start record for { set i 0 } { $i < 12 } { incr i } { uint 0 } -# XYZ gets assigned 1 +# ABC gets assigned 1 record CELLNAME_ID str ABC uint 1 -# ABC gets assigned 0 +# XYZ gets assigned 0 record CELLNAME_ID str XYZ uint 0 diff --git a/testdata/oasis/t2.7.oas b/testdata/oasis/t2.7.oas new file mode 100644 index 0000000000000000000000000000000000000000..9d33c53d9a01fa9d84771799ecb8f2fd818b8b6b GIT binary patch literal 304 ycmY!lcJ=kt^>+;R4CduxWH!_@V0gjKfDBle9i5yRS(qatqZoJ@n2@DLAR7Qj!v=@| literal 0 HcmV?d00001 diff --git a/testdata/oasis/t2.7.ot b/testdata/oasis/t2.7.ot new file mode 100644 index 000000000..3f9326c79 --- /dev/null +++ b/testdata/oasis/t2.7.ot @@ -0,0 +1,35 @@ +# +# t2.7.ot +# Two cells, one just declared but not present +# Unused CELLNAME must not generate an empty cell +# +# begin_lib 0.001 +# begin_cell {XYZ} +# end_cell +# end_lib +# +# + +header + real 0 1000.0 + uint 0 ;# offset table is in start record + for { set i 0 } { $i < 12 } { incr i } { uint 0 } + +# ABC gets assigned 1 +record CELLNAME_ID + str ABC + uint 1 + +# XYZ gets assigned 0 +record CELLNAME_ID + str XYZ + uint 0 + +# Cell XYZ (empty) +record CELL_ID + uint 0 + +# no body. + +tail + diff --git a/testdata/oasis/t2.7_au.txt b/testdata/oasis/t2.7_au.txt new file mode 100644 index 000000000..d6c3a7de4 --- /dev/null +++ b/testdata/oasis/t2.7_au.txt @@ -0,0 +1,4 @@ +begin_lib 0.001 +begin_cell {XYZ} +end_cell +end_lib