[Libreoffice-commits] core.git: drawinglayer/source include/basegfx include/drawinglayer

Armin Le Grand Armin.Le.Grand at cib.de
Fri May 6 10:11:27 UTC 2016


 drawinglayer/source/attribute/fillgraphicattribute.cxx    |    6 
 drawinglayer/source/primitive2d/sceneprimitive2d.cxx      |  251 +++++++-
 drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx |    4 
 drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx   |    4 
 drawinglayer/source/processor3d/zbufferprocessor3d.cxx    |  394 ++++----------
 include/basegfx/matrix/b3dhommatrix.hxx                   |    2 
 include/basegfx/polygon/b3dpolygon.hxx                    |    2 
 include/basegfx/polygon/b3dpolypolygon.hxx                |    2 
 include/drawinglayer/processor3d/zbufferprocessor3d.hxx   |   18 
 9 files changed, 376 insertions(+), 307 deletions(-)

New commits:
commit 657413b5deea11a850970f23cba2cf34a5bdf8ea
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Fri Apr 29 12:30:16 2016 +0200

    Refactor 3D renderer to use multithreading
    
    This try uses full 3D renderers working on the same ZBuffer
    target, but are capable to render one stripe per thread.
    This is rougher in granularity and uses multiple cores better
    than the first try (see gerrit 24393) which was too fine-granular
    being based on scanline render parallelization.
    SecUred some more classes based on SdrPrimitive3D for multi-
    theaded usage (places where local buffered stuff is done)
    
    Change-Id: I4ddd5885ad41dd6432d0695e528818a86e427bfd
    Reviewed-on: https://gerrit.libreoffice.org/24538
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Noel Grandin <noelgrandin at gmail.com>
    Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>

diff --git a/drawinglayer/source/attribute/fillgraphicattribute.cxx b/drawinglayer/source/attribute/fillgraphicattribute.cxx
index 6d70e46..9465af2 100644
--- a/drawinglayer/source/attribute/fillgraphicattribute.cxx
+++ b/drawinglayer/source/attribute/fillgraphicattribute.cxx
@@ -51,6 +51,12 @@ namespace drawinglayer
                 mfOffsetX(fOffsetX),
                 mfOffsetY(fOffsetY)
             {
+                // access once to ensure that the buffered bitmap exists, else
+                // the SolarMutex may be needed to create it. This may not be
+                // available when a renderer works with multi-treading.
+                // When changing this, please check if it is still possible to
+                // use a metafile as texture for a 3D object
+                maGraphic.GetBitmapEx();
             }
 
             ImpFillGraphicAttribute()
diff --git a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx
index 27a4e0d..68acb57 100644
--- a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx
@@ -32,10 +32,105 @@
 #include <svtools/optionsdrawinglayer.hxx>
 #include <drawinglayer/processor3d/geometry2dextractor.hxx>
 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
-
+#include <basegfx/raster/bzpixelraster.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <comphelper/threadpool.hxx>
 
 using namespace com::sun::star;
 
+namespace
+{
+    BitmapEx BPixelRasterToBitmapEx(const basegfx::BPixelRaster& rRaster, sal_uInt16 mnAntiAlialize)
+    {
+        BitmapEx aRetval;
+        const sal_uInt32 nWidth(mnAntiAlialize ? rRaster.getWidth()/mnAntiAlialize : rRaster.getWidth());
+        const sal_uInt32 nHeight(mnAntiAlialize ? rRaster.getHeight()/mnAntiAlialize : rRaster.getHeight());
+
+        if(nWidth && nHeight)
+        {
+            const Size aDestSize(nWidth, nHeight);
+            sal_uInt8 nInitAlpha(255);
+            Bitmap aContent(aDestSize, 24);
+            AlphaMask aAlpha(aDestSize, &nInitAlpha);
+            BitmapWriteAccess* pContent = aContent.AcquireWriteAccess();
+            BitmapWriteAccess* pAlpha = aAlpha.AcquireWriteAccess();
+
+            if (pContent && pAlpha)
+            {
+                if(mnAntiAlialize)
+                {
+                    const sal_uInt16 nDivisor(mnAntiAlialize * mnAntiAlialize);
+
+                    for(sal_uInt32 y(0L); y < nHeight; y++)
+                    {
+                        for(sal_uInt32 x(0L); x < nWidth; x++)
+                        {
+                            sal_uInt16 nRed(0);
+                            sal_uInt16 nGreen(0);
+                            sal_uInt16 nBlue(0);
+                            sal_uInt16 nOpacity(0);
+                            sal_uInt32 nIndex(rRaster.getIndexFromXY(x * mnAntiAlialize, y * mnAntiAlialize));
+
+                            for(sal_uInt32 c(0); c < mnAntiAlialize; c++)
+                            {
+                                for(sal_uInt32 d(0); d < mnAntiAlialize; d++)
+                                {
+                                    const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++));
+                                    nRed = nRed + rPixel.getRed();
+                                    nGreen = nGreen + rPixel.getGreen();
+                                    nBlue = nBlue + rPixel.getBlue();
+                                    nOpacity = nOpacity + rPixel.getOpacity();
+                                }
+
+                                nIndex += rRaster.getWidth() - mnAntiAlialize;
+                            }
+
+                            nOpacity = nOpacity / nDivisor;
+
+                            if(nOpacity)
+                            {
+                                pContent->SetPixel(y, x, BitmapColor(
+                                    (sal_uInt8)(nRed / nDivisor),
+                                    (sal_uInt8)(nGreen / nDivisor),
+                                    (sal_uInt8)(nBlue / nDivisor)));
+                                pAlpha->SetPixel(y, x, BitmapColor(255 - (sal_uInt8)nOpacity));
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    sal_uInt32 nIndex(0L);
+
+                    for(sal_uInt32 y(0L); y < nHeight; y++)
+                    {
+                        for(sal_uInt32 x(0L); x < nWidth; x++)
+                        {
+                            const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++));
+
+                            if(rPixel.getOpacity())
+                            {
+                                pContent->SetPixel(y, x, BitmapColor(rPixel.getRed(), rPixel.getGreen(), rPixel.getBlue()));
+                                pAlpha->SetPixel(y, x, BitmapColor(255 - rPixel.getOpacity()));
+                            }
+                        }
+                    }
+                }
+            }
+
+            aAlpha.ReleaseAccess(pAlpha);
+            Bitmap::ReleaseAccess(pContent);
+
+            aRetval = BitmapEx(aContent, aAlpha);
+
+            // #i101811# set PrefMapMode and PrefSize at newly created Bitmap
+            aRetval.SetPrefMapMode(MAP_PIXEL);
+            aRetval.SetPrefSize(Size(nWidth, nHeight));
+        }
+
+        return aRetval;
+    }
+} // end of anonymous namespace
 
 namespace drawinglayer
 {
@@ -263,49 +358,135 @@ namespace drawinglayer
                 const double fLogicX((aInverseOToV * basegfx::B2DVector(aDiscreteRange.getWidth() * fReduceFactor, 0.0)).getLength());
                 const double fLogicY((aInverseOToV * basegfx::B2DVector(0.0, aDiscreteRange.getHeight() * fReduceFactor)).getLength());
 
-                // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process
-                processor3d::ZBufferProcessor3D aZBufferProcessor3D(
-                    aViewInformation3D,
-                    rViewInformation,
-                    getSdrSceneAttribute(),
-                    getSdrLightingAttribute(),
-                    fLogicX,
-                    fLogicY,
-                    aUnitVisibleRange,
-                    nOversampleValue);
-
-                aZBufferProcessor3D.process(getChildren3D());
-                aZBufferProcessor3D.finish();
+                // generate ViewSizes
+                const double fFullViewSizeX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fLogicX, 0.0)).getLength());
+                const double fFullViewSizeY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fLogicY)).getLength());
 
-                const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = aZBufferProcessor3D.getBitmapEx();
-                const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel());
+                // generate RasterWidth and RasterHeight for visible part
+                const sal_Int32 nRasterWidth((sal_Int32)basegfx::fround(fFullViewSizeX * aUnitVisibleRange.getWidth()) + 1);
+                const sal_Int32 nRasterHeight((sal_Int32)basegfx::fround(fFullViewSizeY * aUnitVisibleRange.getHeight()) + 1);
 
-                if(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight())
+                if(nRasterWidth && nRasterHeight)
                 {
-                    // create transform for the created bitmap in discrete coordinates first.
-                    basegfx::B2DHomMatrix aNew2DTransform;
+                    // create view unit buffer
+                    basegfx::BZPixelRaster aBZPixelRaster(
+                        nOversampleValue ? nRasterWidth * nOversampleValue : nRasterWidth,
+                        nOversampleValue ? nRasterHeight * nOversampleValue : nRasterHeight);
 
-                    aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth());
-                    aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight());
-                    aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX());
-                    aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY());
+                    // check for parallel execution possibilities
+                    static bool bMultithreadAllowed = true;
+                    sal_Int32 nThreadCount(0);
+                    comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool());
 
-                    // transform back to world coordinates for usage in primitive creation
-                    aNew2DTransform *= aInverseOToV;
+                    if(bMultithreadAllowed)
+                    {
+                        nThreadCount = rThreadPool.getWorkerCount();
+
+                        if(nThreadCount > 1)
+                        {
+                            // at least use 10px per processor, so limit number of processors to
+                            // target pixel size divided by 10 (which might be zero what is okay)
+                            nThreadCount = std::min(nThreadCount, nRasterHeight / 10);
+                        }
+                    }
 
-                    // create bitmap primitive and add
-                    const Primitive2DReference xRef(new BitmapPrimitive2D(maOldRenderedBitmap, aNew2DTransform));
-                    aRetval.push_back(xRef);
+                    if(nThreadCount > 1)
+                    {
+                        class Executor : public comphelper::ThreadTask
+                        {
+                        private:
+                            processor3d::ZBufferProcessor3D*            mpZBufferProcessor3D;
+                            const primitive3d::Primitive3DContainer&    mrChildren3D;
+
+                        public:
+                            explicit Executor(
+                                processor3d::ZBufferProcessor3D* pZBufferProcessor3D,
+                                const primitive3d::Primitive3DContainer& rChildren3D)
+                            :   mpZBufferProcessor3D(pZBufferProcessor3D),
+                                mrChildren3D(rChildren3D)
+                            {
+                            }
+
+                            virtual void doWork() override
+                            {
+                                mpZBufferProcessor3D->process(mrChildren3D);
+                                mpZBufferProcessor3D->finish();
+                                delete mpZBufferProcessor3D;
+                            }
+                        };
+
+                        std::vector< processor3d::ZBufferProcessor3D* > aProcessors;
+                        const sal_uInt32 nLinesPerThread(aBZPixelRaster.getHeight() / nThreadCount);
+
+                        for(sal_Int32 a(0); a < nThreadCount; a++)
+                        {
+                            processor3d::ZBufferProcessor3D* pNewZBufferProcessor3D = new processor3d::ZBufferProcessor3D(
+                                aViewInformation3D,
+                                getSdrSceneAttribute(),
+                                getSdrLightingAttribute(),
+                                aUnitVisibleRange,
+                                nOversampleValue,
+                                fFullViewSizeX,
+                                fFullViewSizeY,
+                                aBZPixelRaster,
+                                nLinesPerThread * a,
+                                a + 1 == nThreadCount ? aBZPixelRaster.getHeight() : nLinesPerThread * (a + 1));
+                            aProcessors.push_back(pNewZBufferProcessor3D);
+                            Executor* pExecutor = new Executor(pNewZBufferProcessor3D, getChildren3D());
+                            rThreadPool.pushTask(pExecutor);
+                        }
+
+                        rThreadPool.waitUntilEmpty();
+                    }
+                    else
+                    {
+                        // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process
+                        processor3d::ZBufferProcessor3D aZBufferProcessor3D(
+                            aViewInformation3D,
+                            getSdrSceneAttribute(),
+                            getSdrLightingAttribute(),
+                            aUnitVisibleRange,
+                            nOversampleValue,
+                            fFullViewSizeX,
+                            fFullViewSizeY,
+                            aBZPixelRaster,
+                            0,
+                            aBZPixelRaster.getHeight());
+
+                        aZBufferProcessor3D.process(getChildren3D());
+                        aZBufferProcessor3D.finish();
+                    }
 
-                    // test: Allow to add an outline in the debugger when tests are needed
-                    static bool bAddOutlineToCreated3DSceneRepresentation(false);
+                    const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = BPixelRasterToBitmapEx(aBZPixelRaster, nOversampleValue);
+                    const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel());
 
-                    if(bAddOutlineToCreated3DSceneRepresentation)
+                    if(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight())
                     {
-                        basegfx::B2DPolygon aOutline(basegfx::tools::createUnitPolygon());
-                        aOutline.transform(aNew2DTransform);
-                        const Primitive2DReference xRef2(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0)));
-                        aRetval.push_back(xRef2);
+                        // create transform for the created bitmap in discrete coordinates first.
+                        basegfx::B2DHomMatrix aNew2DTransform;
+
+                        aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth());
+                        aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight());
+                        aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX());
+                        aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY());
+
+                        // transform back to world coordinates for usage in primitive creation
+                        aNew2DTransform *= aInverseOToV;
+
+                        // create bitmap primitive and add
+                        const Primitive2DReference xRef(new BitmapPrimitive2D(maOldRenderedBitmap, aNew2DTransform));
+                        aRetval.push_back(xRef);
+
+                        // test: Allow to add an outline in the debugger when tests are needed
+                        static bool bAddOutlineToCreated3DSceneRepresentation(false);
+
+                        if(bAddOutlineToCreated3DSceneRepresentation)
+                        {
+                            basegfx::B2DPolygon aOutline(basegfx::tools::createUnitPolygon());
+                            aOutline.transform(aNew2DTransform);
+                            const Primitive2DReference xRef2(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0)));
+                            aRetval.push_back(xRef2);
+                        }
                     }
                 }
             }
diff --git a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
index a5fe0dd..be15838 100644
--- a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
@@ -375,6 +375,8 @@ namespace drawinglayer
             // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
             if(getPolyPolygon().count() && !maSlices.size())
             {
+                ::osl::MutexGuard aGuard( m_aMutex );
+
                 const_cast< SdrExtrudePrimitive3D& >(*this).impCreateSlices();
             }
 
@@ -488,6 +490,8 @@ namespace drawinglayer
                     (!getBuffered3DDecomposition().empty()
                         && *mpLastRLGViewInformation != rViewInformation))
                 {
+                    ::osl::MutexGuard aGuard( m_aMutex );
+
                     // conditions of last local decomposition with reduced lines have changed. Remember
                     // new one and clear current decompositiopn
                     SdrExtrudePrimitive3D* pThat = const_cast< SdrExtrudePrimitive3D* >(this);
diff --git a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
index be66c16..f831aba 100644
--- a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
@@ -231,6 +231,8 @@ namespace drawinglayer
             // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
             if(getPolyPolygon().count() && !maSlices.size())
             {
+                ::osl::MutexGuard aGuard( m_aMutex );
+
                 const_cast< SdrLathePrimitive3D& >(*this).impCreateSlices();
             }
 
@@ -350,6 +352,8 @@ namespace drawinglayer
                     (!getBuffered3DDecomposition().empty()
                         && *mpLastRLGViewInformation != rViewInformation))
                 {
+                    ::osl::MutexGuard aGuard( m_aMutex );
+
                     // conditions of last local decomposition with reduced lines have changed. Remember
                     // new one and clear current decompositiopn
                     SdrLathePrimitive3D* pThat = const_cast< SdrLathePrimitive3D* >(this);
diff --git a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
index 0334c91..3944f83 100644
--- a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
+++ b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
@@ -19,7 +19,6 @@
 
 #include <drawinglayer/processor3d/zbufferprocessor3d.hxx>
 #include <basegfx/raster/bpixelraster.hxx>
-#include <vcl/bitmapaccess.hxx>
 #include <basegfx/raster/rasterconvert3d.hxx>
 #include <basegfx/raster/bzpixelraster.hxx>
 #include <drawinglayer/attribute/materialattribute3d.hxx>
@@ -35,100 +34,6 @@
 
 using namespace com::sun::star;
 
-namespace
-{
-    BitmapEx BPixelRasterToBitmapEx(const basegfx::BPixelRaster& rRaster, sal_uInt16 mnAntiAlialize)
-    {
-        BitmapEx aRetval;
-        const sal_uInt32 nWidth(mnAntiAlialize ? rRaster.getWidth()/mnAntiAlialize : rRaster.getWidth());
-        const sal_uInt32 nHeight(mnAntiAlialize ? rRaster.getHeight()/mnAntiAlialize : rRaster.getHeight());
-
-        if(nWidth && nHeight)
-        {
-            const Size aDestSize(nWidth, nHeight);
-            sal_uInt8 nInitAlpha(255);
-            Bitmap aContent(aDestSize, 24);
-            AlphaMask aAlpha(aDestSize, &nInitAlpha);
-            BitmapWriteAccess* pContent = aContent.AcquireWriteAccess();
-            BitmapWriteAccess* pAlpha = aAlpha.AcquireWriteAccess();
-
-            if (pContent && pAlpha)
-            {
-                if(mnAntiAlialize)
-                {
-                    const sal_uInt16 nDivisor(mnAntiAlialize * mnAntiAlialize);
-
-                    for(sal_uInt32 y(0L); y < nHeight; y++)
-                    {
-                        for(sal_uInt32 x(0L); x < nWidth; x++)
-                        {
-                            sal_uInt16 nRed(0);
-                            sal_uInt16 nGreen(0);
-                            sal_uInt16 nBlue(0);
-                            sal_uInt16 nOpacity(0);
-                            sal_uInt32 nIndex(rRaster.getIndexFromXY(x * mnAntiAlialize, y * mnAntiAlialize));
-
-                            for(sal_uInt32 c(0); c < mnAntiAlialize; c++)
-                            {
-                                for(sal_uInt32 d(0); d < mnAntiAlialize; d++)
-                                {
-                                    const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++));
-                                    nRed = nRed + rPixel.getRed();
-                                    nGreen = nGreen + rPixel.getGreen();
-                                    nBlue = nBlue + rPixel.getBlue();
-                                    nOpacity = nOpacity + rPixel.getOpacity();
-                                }
-
-                                nIndex += rRaster.getWidth() - mnAntiAlialize;
-                            }
-
-                            nOpacity = nOpacity / nDivisor;
-
-                            if(nOpacity)
-                            {
-                                pContent->SetPixel(y, x, BitmapColor(
-                                    (sal_uInt8)(nRed / nDivisor),
-                                    (sal_uInt8)(nGreen / nDivisor),
-                                    (sal_uInt8)(nBlue / nDivisor)));
-                                pAlpha->SetPixel(y, x, BitmapColor(255 - (sal_uInt8)nOpacity));
-                            }
-                        }
-                    }
-                }
-                else
-                {
-                    sal_uInt32 nIndex(0L);
-
-                    for(sal_uInt32 y(0L); y < nHeight; y++)
-                    {
-                        for(sal_uInt32 x(0L); x < nWidth; x++)
-                        {
-                            const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++));
-
-                            if(rPixel.getOpacity())
-                            {
-                                pContent->SetPixel(y, x, BitmapColor(rPixel.getRed(), rPixel.getGreen(), rPixel.getBlue()));
-                                pAlpha->SetPixel(y, x, BitmapColor(255 - rPixel.getOpacity()));
-                            }
-                        }
-                    }
-                }
-            }
-
-            aAlpha.ReleaseAccess(pAlpha);
-            Bitmap::ReleaseAccess(pContent);
-
-            aRetval = BitmapEx(aContent, aAlpha);
-
-            // #i101811# set PrefMapMode and PrefSize at newly created Bitmap
-            aRetval.SetPrefMapMode(MAP_PIXEL);
-            aRetval.SetPrefSize(Size(nWidth, nHeight));
-        }
-
-        return aRetval;
-    }
-} // end of anonymous namespace
-
 class ZBufferRasterConverter3D : public basegfx::RasterConverter3D
 {
 private:
@@ -536,211 +441,188 @@ namespace drawinglayer
     {
         void ZBufferProcessor3D::rasterconvertB3DPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolygon& rHairline) const
         {
-            if(mpBZPixelRaster)
+            if(getTransparenceCounter())
             {
-                if(getTransparenceCounter())
+                // transparent output; record for later sorting and painting from
+                // back to front
+                if(!mpRasterPrimitive3Ds)
                 {
-                    // transparent output; record for later sorting and painting from
-                    // back to front
-                    if(!mpRasterPrimitive3Ds)
-                    {
-                        const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >;
-                    }
-
-                    mpRasterPrimitive3Ds->push_back(RasterPrimitive3D(
-                        getGeoTexSvx(),
-                        getTransparenceGeoTexSvx(),
-                        rMaterial,
-                        basegfx::B3DPolyPolygon(rHairline),
-                        getModulate(),
-                        getFilter(),
-                        getSimpleTextureActive(),
-                        true));
+                    const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >;
                 }
-                else
+
+                mpRasterPrimitive3Ds->push_back(RasterPrimitive3D(
+                    getGeoTexSvx(),
+                    getTransparenceGeoTexSvx(),
+                    rMaterial,
+                    basegfx::B3DPolyPolygon(rHairline),
+                    getModulate(),
+                    getFilter(),
+                    getSimpleTextureActive(),
+                    true));
+            }
+            else
+            {
+                // do rasterconversion
+                mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
+
+                if(mnAntiAlialize > 1)
                 {
-                    // do rasterconversion
-                    mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
+                    const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
 
-                    if(mnAntiAlialize > 1)
+                    if(bForceLineSnap)
                     {
-                        const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
+                        basegfx::B3DHomMatrix aTransform;
+                        basegfx::B3DPolygon aSnappedHairline(rHairline);
+                        const double fScaleDown(1.0 / mnAntiAlialize);
+                        const double fScaleUp(mnAntiAlialize);
 
-                        if(bForceLineSnap)
-                        {
-                            basegfx::B3DHomMatrix aTransform;
-                            basegfx::B3DPolygon aSnappedHairline(rHairline);
-                            const double fScaleDown(1.0 / mnAntiAlialize);
-                            const double fScaleUp(mnAntiAlialize);
-
-                            // take oversampling out
-                            aTransform.scale(fScaleDown, fScaleDown, 1.0);
-                            aSnappedHairline.transform(aTransform);
+                        // take oversampling out
+                        aTransform.scale(fScaleDown, fScaleDown, 1.0);
+                        aSnappedHairline.transform(aTransform);
 
-                            // snap to integer
-                            aSnappedHairline = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline);
+                        // snap to integer
+                        aSnappedHairline = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline);
 
-                            // add oversampling again
-                            aTransform.identity();
-                            aTransform.scale(fScaleUp, fScaleUp, 1.0);
+                        // add oversampling again
+                        aTransform.identity();
+                        aTransform.scale(fScaleUp, fScaleUp, 1.0);
 
-                            aSnappedHairline.transform(aTransform);
+                        aSnappedHairline.transform(aTransform);
 
-                            mpZBufferRasterConverter3D->rasterconvertB3DPolygon(aSnappedHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize);
-                        }
-                        else
-                        {
-                            mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize);
-                        }
+                        mpZBufferRasterConverter3D->rasterconvertB3DPolygon(aSnappedHairline, mnStartLine, mnStopLine, mnAntiAlialize);
                     }
                     else
                     {
-                        mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), 1);
+                        mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, mnStartLine, mnStopLine, mnAntiAlialize);
                     }
                 }
+                else
+                {
+                    mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, mnStartLine, mnStopLine, 1);
+                }
             }
         }
 
         void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolyPolygon& rFill) const
         {
-            if(mpBZPixelRaster)
+            if(getTransparenceCounter())
             {
-                if(getTransparenceCounter())
+                // transparent output; record for later sorting and painting from
+                // back to front
+                if(!mpRasterPrimitive3Ds)
                 {
-                    // transparent output; record for later sorting and painting from
-                    // back to front
-                    if(!mpRasterPrimitive3Ds)
-                    {
-                        const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >;
-                    }
-
-                    mpRasterPrimitive3Ds->push_back(RasterPrimitive3D(
-                        getGeoTexSvx(),
-                        getTransparenceGeoTexSvx(),
-                        rMaterial,
-                        rFill,
-                        getModulate(),
-                        getFilter(),
-                        getSimpleTextureActive(),
-                        false));
-                }
-                else
-                {
-                    mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
-                    mpZBufferRasterConverter3D->rasterconvertB3DPolyPolygon(rFill, &maInvEyeToView, 0, mpBZPixelRaster->getHeight());
+                    const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >;
                 }
+
+                mpRasterPrimitive3Ds->push_back(RasterPrimitive3D(
+                    getGeoTexSvx(),
+                    getTransparenceGeoTexSvx(),
+                    rMaterial,
+                    rFill,
+                    getModulate(),
+                    getFilter(),
+                    getSimpleTextureActive(),
+                    false));
+            }
+            else
+            {
+                mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
+                mpZBufferRasterConverter3D->rasterconvertB3DPolyPolygon(rFill, &maInvEyeToView, mnStartLine, mnStopLine);
             }
         }
 
         ZBufferProcessor3D::ZBufferProcessor3D(
             const geometry::ViewInformation3D& rViewInformation3D,
-            const geometry::ViewInformation2D& rViewInformation2D,
             const attribute::SdrSceneAttribute& rSdrSceneAttribute,
             const attribute::SdrLightingAttribute& rSdrLightingAttribute,
-            double fSizeX,
-            double fSizeY,
             const basegfx::B2DRange& rVisiblePart,
-            sal_uInt16 nAntiAlialize)
+            sal_uInt16 nAntiAlialize,
+            double fFullViewSizeX,
+            double fFullViewSizeY,
+            basegfx::BZPixelRaster& rBZPixelRaster,
+            sal_uInt32 nStartLine,
+            sal_uInt32 nStopLine)
         :   DefaultProcessor3D(rViewInformation3D, rSdrSceneAttribute, rSdrLightingAttribute),
-            mpBZPixelRaster(nullptr),
+            mrBZPixelRaster(rBZPixelRaster),
             maInvEyeToView(),
             mpZBufferRasterConverter3D(nullptr),
             mnAntiAlialize(nAntiAlialize),
-            mpRasterPrimitive3Ds(nullptr)
+            mpRasterPrimitive3Ds(nullptr),
+            mnStartLine(nStartLine),
+            mnStopLine(nStopLine)
         {
-            // generate ViewSizes
-            const double fFullViewSizeX((rViewInformation2D.getObjectToViewTransformation() * basegfx::B2DVector(fSizeX, 0.0)).getLength());
-            const double fFullViewSizeY((rViewInformation2D.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fSizeY)).getLength());
-            const double fViewSizeX(fFullViewSizeX * rVisiblePart.getWidth());
-            const double fViewSizeY(fFullViewSizeY * rVisiblePart.getHeight());
-
-            // generate RasterWidth and RasterHeight
-            const sal_uInt32 nRasterWidth((sal_uInt32)basegfx::fround(fViewSizeX) + 1);
-            const sal_uInt32 nRasterHeight((sal_uInt32)basegfx::fround(fViewSizeY) + 1);
+            // create DeviceToView for Z-Buffer renderer since Z is handled
+            // different from standard 3D transformations (Z is mirrored). Also
+            // the transformation includes the step from unit device coordinates
+            // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete]
+            basegfx::B3DHomMatrix aDeviceToView;
 
-            if(nRasterWidth && nRasterHeight)
             {
-                // create view unit buffer
-                mpBZPixelRaster = new basegfx::BZPixelRaster(
-                    mnAntiAlialize ? nRasterWidth * mnAntiAlialize : nRasterWidth,
-                    mnAntiAlialize ? nRasterHeight * mnAntiAlialize : nRasterHeight);
-                OSL_ENSURE(mpBZPixelRaster, "ZBufferProcessor3D: Could not allocate basegfx::BZPixelRaster (!)");
-
-                // create DeviceToView for Z-Buffer renderer since Z is handled
-                // different from standard 3D transformations (Z is mirrored). Also
-                // the transformation includes the step from unit device coordinates
-                // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete]
-
-                basegfx::B3DHomMatrix aDeviceToView;
-
-                {
-                    // step one:
-                    //
-                    // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
-                    // necessary to
-                    // - flip Y due to screen orientation
-                    // - flip Z due to Z-Buffer orientation from back to front
-
-                    aDeviceToView.scale(0.5, -0.5, -0.5);
-                    aDeviceToView.translate(0.5, 0.5, 0.5);
-                }
+                // step one:
+                //
+                // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
+                // necessary to
+                // - flip Y due to screen orientation
+                // - flip Z due to Z-Buffer orientation from back to front
+
+                aDeviceToView.scale(0.5, -0.5, -0.5);
+                aDeviceToView.translate(0.5, 0.5, 0.5);
+            }
 
-                {
-                    // step two:
-                    //
-                    // bring from [0.0 .. 1.0] in X,Y and Z to view coordinates
-                    //
-                    // #i102611#
-                    // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0]
-                    // could be used, but a 'unused' value is needed, so '0' is used what reduces
-                    // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors
-                    // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen.
-                    // Instead of checking those by basegfx::fTools methods which would cost
-                    // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer
-                    // range, thus resulting in [1.5 .. 65534.5]
-                    const double fMaxZDepth(65533.0);
-                    aDeviceToView.translate(-rVisiblePart.getMinX(), -rVisiblePart.getMinY(), 0.0);
-
-                    if(mnAntiAlialize)
-                        aDeviceToView.scale(fFullViewSizeX * mnAntiAlialize, fFullViewSizeY * mnAntiAlialize, fMaxZDepth);
-                    else
-                        aDeviceToView.scale(fFullViewSizeX, fFullViewSizeY, fMaxZDepth);
+            {
+                // step two:
+                //
+                // bring from [0.0 .. 1.0] in X,Y and Z to view coordinates
+                //
+                // #i102611#
+                // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0]
+                // could be used, but a 'unused' value is needed, so '0' is used what reduces
+                // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors
+                // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen.
+                // Instead of checking those by basegfx::fTools methods which would cost
+                // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer
+                // range, thus resulting in [1.5 .. 65534.5]
+                const double fMaxZDepth(65533.0);
+                aDeviceToView.translate(-rVisiblePart.getMinX(), -rVisiblePart.getMinY(), 0.0);
 
-                    aDeviceToView.translate(0.0, 0.0, 1.5);
-                }
+                if(mnAntiAlialize)
+                    aDeviceToView.scale(fFullViewSizeX * mnAntiAlialize, fFullViewSizeY * mnAntiAlialize, fMaxZDepth);
+                else
+                    aDeviceToView.scale(fFullViewSizeX, fFullViewSizeY, fMaxZDepth);
 
-                // update local ViewInformation3D with own DeviceToView
-                const geometry::ViewInformation3D aNewViewInformation3D(
-                    getViewInformation3D().getObjectTransformation(),
-                    getViewInformation3D().getOrientation(),
-                    getViewInformation3D().getProjection(),
-                    aDeviceToView,
-                    getViewInformation3D().getViewTime(),
-                    getViewInformation3D().getExtendedInformationSequence());
-                updateViewInformation(aNewViewInformation3D);
-
-                // prepare inverse EyeToView transformation. This can be done in constructor
-                // since changes in object transformations when processing TransformPrimitive3Ds
-                // do not influence this prepared partial transformation
-                maInvEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
-                maInvEyeToView.invert();
-
-                // prepare maRasterRange
-                maRasterRange.reset();
-                maRasterRange.expand(basegfx::B2DPoint(0.0, 0.0));
-                maRasterRange.expand(basegfx::B2DPoint(mpBZPixelRaster->getWidth(), mpBZPixelRaster->getHeight()));
-
-                // create the raster converter
-                mpZBufferRasterConverter3D = new ZBufferRasterConverter3D(*mpBZPixelRaster, *this);
+                aDeviceToView.translate(0.0, 0.0, 1.5);
             }
+
+            // update local ViewInformation3D with own DeviceToView
+            const geometry::ViewInformation3D aNewViewInformation3D(
+                getViewInformation3D().getObjectTransformation(),
+                getViewInformation3D().getOrientation(),
+                getViewInformation3D().getProjection(),
+                aDeviceToView,
+                getViewInformation3D().getViewTime(),
+                getViewInformation3D().getExtendedInformationSequence());
+            updateViewInformation(aNewViewInformation3D);
+
+            // prepare inverse EyeToView transformation. This can be done in constructor
+            // since changes in object transformations when processing TransformPrimitive3Ds
+            // do not influence this prepared partial transformation
+            maInvEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
+            maInvEyeToView.invert();
+
+            // prepare maRasterRange
+            maRasterRange.reset();
+            maRasterRange.expand(basegfx::B2DPoint(0.0, nStartLine));
+            maRasterRange.expand(basegfx::B2DPoint(mrBZPixelRaster.getWidth(), nStopLine));
+
+            // create the raster converter
+            mpZBufferRasterConverter3D = new ZBufferRasterConverter3D(mrBZPixelRaster, *this);
         }
 
         ZBufferProcessor3D::~ZBufferProcessor3D()
         {
-            if(mpBZPixelRaster)
+            if(mpZBufferRasterConverter3D)
             {
                 delete mpZBufferRasterConverter3D;
-                delete mpBZPixelRaster;
             }
 
             if(mpRasterPrimitive3Ds)
@@ -795,16 +677,6 @@ namespace drawinglayer
                 mpRasterPrimitive3Ds = nullptr;
             }
         }
-
-        BitmapEx ZBufferProcessor3D::getBitmapEx() const
-        {
-            if(mpBZPixelRaster)
-            {
-                return BPixelRasterToBitmapEx(*mpBZPixelRaster, mnAntiAlialize);
-            }
-
-            return BitmapEx();
-        }
     } // end of namespace processor3d
 } // end of namespace drawinglayer
 
diff --git a/include/basegfx/matrix/b3dhommatrix.hxx b/include/basegfx/matrix/b3dhommatrix.hxx
index b8e1c5b..ec8ee34 100644
--- a/include/basegfx/matrix/b3dhommatrix.hxx
+++ b/include/basegfx/matrix/b3dhommatrix.hxx
@@ -34,7 +34,7 @@ namespace basegfx
     class BASEGFX_DLLPUBLIC B3DHomMatrix
     {
     public:
-        typedef o3tl::cow_wrapper< Impl3DHomMatrix > ImplType;
+        typedef o3tl::cow_wrapper< Impl3DHomMatrix, o3tl::ThreadSafeRefCountingPolicy > ImplType;
 
     private:
         ImplType                                     mpImpl;
diff --git a/include/basegfx/polygon/b3dpolygon.hxx b/include/basegfx/polygon/b3dpolygon.hxx
index 6c9c9b9..d32968b 100644
--- a/include/basegfx/polygon/b3dpolygon.hxx
+++ b/include/basegfx/polygon/b3dpolygon.hxx
@@ -42,7 +42,7 @@ namespace basegfx
     class BASEGFX_DLLPUBLIC B3DPolygon
     {
     public:
-        typedef o3tl::cow_wrapper< ImplB3DPolygon > ImplType;
+        typedef o3tl::cow_wrapper< ImplB3DPolygon, o3tl::ThreadSafeRefCountingPolicy > ImplType;
 
     private:
         // internal data.
diff --git a/include/basegfx/polygon/b3dpolypolygon.hxx b/include/basegfx/polygon/b3dpolypolygon.hxx
index ea47e33..9e3472d 100644
--- a/include/basegfx/polygon/b3dpolypolygon.hxx
+++ b/include/basegfx/polygon/b3dpolypolygon.hxx
@@ -38,7 +38,7 @@ namespace basegfx
     class BASEGFX_DLLPUBLIC B3DPolyPolygon
     {
     public:
-        typedef o3tl::cow_wrapper< ImplB3DPolyPolygon > ImplType;
+        typedef o3tl::cow_wrapper< ImplB3DPolyPolygon, o3tl::ThreadSafeRefCountingPolicy > ImplType;
 
     private:
         ImplType                                        mpPolyPolygon;
diff --git a/include/drawinglayer/processor3d/zbufferprocessor3d.hxx b/include/drawinglayer/processor3d/zbufferprocessor3d.hxx
index 8e3f6d4..0f58a7f 100644
--- a/include/drawinglayer/processor3d/zbufferprocessor3d.hxx
+++ b/include/drawinglayer/processor3d/zbufferprocessor3d.hxx
@@ -56,7 +56,7 @@ namespace drawinglayer
         {
         private:
             /// the raster target, a Z-Buffer
-            basegfx::BZPixelRaster* mpBZPixelRaster;
+            basegfx::BZPixelRaster& mrBZPixelRaster;
 
             /// inverse of EyeToView for rasterconversion with evtl. Phong shading
             basegfx::B3DHomMatrix maInvEyeToView;
@@ -74,6 +74,9 @@ namespace drawinglayer
              */
             std::vector< RasterPrimitive3D >* mpRasterPrimitive3Ds;
 
+            sal_uInt32 mnStartLine;
+            sal_uInt32 mnStopLine;
+
             // rasterconversions for filled and non-filled polygons
 
             virtual void rasterconvertB3DPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolygon& rHairline) const override;
@@ -82,19 +85,18 @@ namespace drawinglayer
         public:
             ZBufferProcessor3D(
                 const geometry::ViewInformation3D& rViewInformation3D,
-                const geometry::ViewInformation2D& rViewInformation2D,
                 const attribute::SdrSceneAttribute& rSdrSceneAttribute,
                 const attribute::SdrLightingAttribute& rSdrLightingAttribute,
-                double fSizeX,
-                double fSizeY,
                 const basegfx::B2DRange& rVisiblePart,
-                sal_uInt16 nAntiAlialize);
+                sal_uInt16 nAntiAlialize,
+                double fFullViewSizeX,
+                double fFullViewSizeY,
+                basegfx::BZPixelRaster& rBZPixelRaster,
+                sal_uInt32 nStartLine,
+                sal_uInt32 nStopLine);
             virtual ~ZBufferProcessor3D();
 
             void finish();
-
-            /// get the result as bitmapEx
-            BitmapEx getBitmapEx() const;
         };
     }
 }


More information about the Libreoffice-commits mailing list