basegfx/source/polygon/b3dpolygon.cxx | 57 +++------------------------------ include/basegfx/polygon/b3dpolygon.hxx | 2 - 2 files changed, 7 insertions(+), 52 deletions(-)
New commits: commit 115f60037409c511ae01006dedd32306ddf274ff Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Wed Jul 10 11:12:04 2024 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Wed Jul 10 19:04:37 2024 +0200 tsan: ImplB3DPolygon cannot have mutable state because it lives inside a cow_wrapper, which means multiple threads will see inconsistent state. WARNING: ThreadSanitizer: data race (pid=1448100) Read of size 1 at 0x7218002d5a48 by thread T333: 0 ImplB3DPolygon::getNormal() basegfx/source/polygon/b3dpolygon.cxx:998 (libbasegfxlo.so+0xef47a) 1 basegfx::B3DPolygon::getNormal() const basegfx/source/polygon/b3dpolygon.cxx:1477 (libbasegfxlo.so+0xe1834) 2 drawinglayer::processor3d::DefaultProcessor3D::impRenderPolyPolygonMaterialPrimitive3D(drawinglayer::primitive3d::PolyPolygonMaterialPrimitive3D const&) const drawinglayer/source/processor3d/defaultprocessor3d.cxx:424 (libdrawinglayerlo.so+0x1ed388) 3 drawinglayer::processor3d::DefaultProcessor3D::processBasePrimitive3D(drawinglayer::primitive3d::BasePrimitive3D const&) drawinglayer/source/processor3d/defaultprocessor3d.cxx:531 (libdrawinglayerlo.so+0x1edb6f) 4 drawinglayer::processor3d::BaseProcessor3D::process(drawinglayer::primitive3d::Primitive3DContainer const&) drawinglayer/source/processor3d/baseprocessor3d.cxx:57 (libdrawinglayerlo.so+0x1e91c1) 5 drawinglayer::processor3d::DefaultProcessor3D::processBasePrimitive3D(drawinglayer::primitive3d::BasePrimitive3D const&) drawinglayer/source/processor3d/defaultprocessor3d.cxx:543 (libdrawinglayerlo.so+0x1edbe4) 6 drawinglayer::processor3d::BaseProcessor3D::process(drawinglayer::primitive3d::Primitive3DContainer const&) drawinglayer/source/processor3d/baseprocessor3d.cxx:57 (libdrawinglayerlo.so+0x1e91c1) 7 drawinglayer::primitive2d::ScenePrimitive2D::create2DDecomposition(drawinglayer::geometry::ViewInformation2D const&) const::Executor::doWork() drawinglayer/source/primitive2d/sceneprimitive2d.cxx:462 (libdrawinglayerlo.so+0x12469f) 8 comphelper::ThreadTask::exec() comphelper/source/misc/threadpool.cxx:319 (libcomphelper.so+0x2bd587) 9 comphelper::ThreadPool::ThreadWorker::execute() comphelper/source/misc/threadpool.cxx:85 (libcomphelper.so+0x2c3930) 10 salhelper::Thread::run() salhelper/source/thread.cxx:39 (libuno_salhelpergcc3.so.3+0x5d22) 11 non-virtual thunk to salhelper::Thread::run() salhelper/source/thread.cxx:? (libuno_salhelpergcc3.so.3+0x5ed9) 12 threadFunc include/osl/thread.hxx:189 (libuno_salhelpergcc3.so.3+0x6b1e) 13 osl_thread_start_Impl(void*) sal/osl/unx/thread.cxx:237 (libuno_sal.so.3+0xfc937) Previous write of size 8 at 0x7218002d5a48 by thread T334: 0 operator new(unsigned long) /home/noel/llvm-project/compiler-rt/lib/tsan/rtl/tsan_new_delete.cpp:64 (discriminator 8) (cppunittester+0x10c8a1) 1 o3tl::cow_wrapper<ImplB3DPolygon, o3tl::ThreadSafeRefCountingPolicy>::make_unique() include/o3tl/cow_wrapper.hxx:304 (libbasegfxlo.so+0xfe798) 2 o3tl::cow_wrapper<ImplB3DPolygon, o3tl::ThreadSafeRefCountingPolicy>::operator->() include/o3tl/cow_wrapper.hxx:329 (libbasegfxlo.so+0xef0e5) 3 basegfx::B3DPolygon::getNormal() const basegfx/source/polygon/b3dpolygon.cxx:1477 (libbasegfxlo.so+0xe1825) 4 drawinglayer::processor3d::DefaultProcessor3D::impRenderPolyPolygonMaterialPrimitive3D(drawinglayer::primitive3d::PolyPolygonMaterialPrimitive3D const&) const drawinglayer/source/processor3d/defaultprocessor3d.cxx:424 (libdrawinglayerlo.so+0x1ed388) 5 drawinglayer::processor3d::DefaultProcessor3D::processBasePrimitive3D(drawinglayer::primitive3d::BasePrimitive3D const&) drawinglayer/source/processor3d/defaultprocessor3d.cxx:531 (libdrawinglayerlo.so+0x1edb6f) 6 drawinglayer::processor3d::BaseProcessor3D::process(drawinglayer::primitive3d::Primitive3DContainer const&) drawinglayer/source/processor3d/baseprocessor3d.cxx:57 (libdrawinglayerlo.so+0x1e91c1) 7 drawinglayer::processor3d::DefaultProcessor3D::processBasePrimitive3D(drawinglayer::primitive3d::BasePrimitive3D const&) drawinglayer/source/processor3d/defaultprocessor3d.cxx:543 (libdrawinglayerlo.so+0x1edbe4) 8 drawinglayer::processor3d::BaseProcessor3D::process(drawinglayer::primitive3d::Primitive3DContainer const&) drawinglayer/source/processor3d/baseprocessor3d.cxx:57 (libdrawinglayerlo.so+0x1e91c1) 9 drawinglayer::primitive2d::ScenePrimitive2D::create2DDecomposition(drawinglayer::geometry::ViewInformation2D const&) const::Executor::doWork() drawinglayer/source/primitive2d/sceneprimitive2d.cxx:462 (libdrawinglayerlo.so+0x12469f) 10 comphelper::ThreadTask::exec() comphelper/source/misc/threadpool.cxx:319 (libcomphelper.so+0x2bd587) 11 comphelper::ThreadPool::ThreadWorker::execute() comphelper/source/misc/threadpool.cxx:85 (libcomphelper.so+0x2c3930) 12 salhelper::Thread::run() salhelper/source/thread.cxx:39 (libuno_salhelpergcc3.so.3+0x5d22) 13 non-virtual thunk to salhelper::Thread::run() salhelper/source/thread.cxx:? (libuno_salhelpergcc3.so.3+0x5ed9) 14 threadFunc include/osl/thread.hxx:189 (libuno_salhelpergcc3.so.3+0x6b1e) 15 osl_thread_start_Impl(void*) sal/osl/unx/thread.cxx:237 (libuno_sal.so.3+0xfc937) Change-Id: I9a12e2178cfad07f0a23b5dc4c502ce16ef92fb1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170275 Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> Tested-by: Jenkins Reviewed-by: Armin Le Grand <armin.le.gr...@me.com> diff --git a/basegfx/source/polygon/b3dpolygon.cxx b/basegfx/source/polygon/b3dpolygon.cxx index ebd9e3f4f7ea..f17f974e2fb7 100644 --- a/basegfx/source/polygon/b3dpolygon.cxx +++ b/basegfx/source/polygon/b3dpolygon.cxx @@ -693,41 +693,22 @@ class ImplB3DPolygon // and may be zero. std::unique_ptr<TextureCoordinate2D> mpTextureCoordinates; - // The calculated plane normal. mbPlaneNormalValid says if it's valid. - ::basegfx::B3DVector maPlaneNormal; - // flag which decides if this polygon is opened or closed bool mbIsClosed : 1; - // flag which says if maPlaneNormal is up-to-date - bool mbPlaneNormalValid : 1; - -protected: - void invalidatePlaneNormal() - { - if(mbPlaneNormalValid) - { - mbPlaneNormalValid = false; - } - } - public: // This constructor is only used from the static identity polygon, thus // the RefCount is set to 1 to never 'delete' this static incarnation. ImplB3DPolygon() : maPoints(0), - maPlaneNormal(::basegfx::B3DVector::getEmptyVector()), - mbIsClosed(false), - mbPlaneNormalValid(true) + mbIsClosed(false) { // complete initialization with defaults } ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied) : maPoints(rToBeCopied.maPoints), - maPlaneNormal(rToBeCopied.maPlaneNormal), - mbIsClosed(rToBeCopied.mbIsClosed), - mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid) + mbIsClosed(rToBeCopied.mbIsClosed) { // complete initialization using copy if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed()) @@ -748,9 +729,7 @@ public: ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount) : maPoints(rToBeCopied.maPoints, nIndex, nCount), - maPlaneNormal(::basegfx::B3DVector::getEmptyVector()), - mbIsClosed(rToBeCopied.mbIsClosed), - mbPlaneNormalValid(false) + mbIsClosed(rToBeCopied.mbIsClosed) { // complete initialization using partly copy if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed()) @@ -916,7 +895,6 @@ public: void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue) { maPoints.setCoordinate(nIndex, rValue); - invalidatePlaneNormal(); } void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount) @@ -926,7 +904,6 @@ public: CoordinateData3D aCoordinate(rPoint); maPoints.insert(nIndex, aCoordinate, nCount); - invalidatePlaneNormal(); if(mpBColors) { @@ -987,15 +964,9 @@ public: mpBColors.reset(); } - const ::basegfx::B3DVector& getNormal() const + ::basegfx::B3DVector getNormal() const { - if(!mbPlaneNormalValid) - { - const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal(); - const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true; - } - - return maPlaneNormal; + return maPoints.getNormal(); } const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const @@ -1108,7 +1079,6 @@ public: return; maPoints.insert(nIndex, rSource.maPoints); - invalidatePlaneNormal(); if(rSource.mpBColors && rSource.mpBColors->isUsed()) { @@ -1168,7 +1138,6 @@ public: return; maPoints.remove(nIndex, nCount); - invalidatePlaneNormal(); if(mpBColors) { @@ -1208,12 +1177,6 @@ public: maPoints.flip(); - if(mbPlaneNormalValid) - { - // mirror plane normal - maPlaneNormal = -maPlaneNormal; - } - if(mpBColors) { mpBColors->flip(); @@ -1368,14 +1331,6 @@ public: void transform(const ::basegfx::B3DHomMatrix& rMatrix) { maPoints.transform(rMatrix); - - // Here, it seems to be possible to transform a valid plane normal and to avoid - // invalidation, but it's not true. If the transformation contains shears or e.g. - // perspective projection, the orthogonality to the transformed plane will not - // be preserved. It may be possible to test that at the matrix to not invalidate in - // all cases or to extract a matrix which does not 'shear' the vector which is - // a normal in this case. As long as this is not sure, i will just invalidate. - invalidatePlaneNormal(); } }; @@ -1459,7 +1414,7 @@ namespace basegfx mpPolygon->clearBColors(); } - B3DVector const & B3DPolygon::getNormal() const + B3DVector B3DPolygon::getNormal() const { return mpPolygon->getNormal(); } diff --git a/include/basegfx/polygon/b3dpolygon.hxx b/include/basegfx/polygon/b3dpolygon.hxx index 13f8ed293f59..09544766e662 100644 --- a/include/basegfx/polygon/b3dpolygon.hxx +++ b/include/basegfx/polygon/b3dpolygon.hxx @@ -76,7 +76,7 @@ namespace basegfx void clearBColors(); // Normals interface - B3DVector const & getNormal() const; // plane normal + B3DVector getNormal() const; // plane normal B3DVector const & getNormal(sal_uInt32 nIndex) const; // normal in each point void setNormal(sal_uInt32 nIndex, const B3DVector& rValue); void transformNormals(const B3DHomMatrix& rMatrix);