diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2016-04-29 12:30:16 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@cib.de> | 2016-05-06 10:11:03 +0000 |
commit | 657413b5deea11a850970f23cba2cf34a5bdf8ea (patch) | |
tree | 01d1daef3fe03fe7ad271e8efecaf189b94fe261 | |
parent | d324b4b3e1d32b25a6347f2f77ae921a584ee9b0 (diff) |
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@libreoffice.org>
Reviewed-by: Noel Grandin <noelgrandin@gmail.com>
Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
-rw-r--r-- | drawinglayer/source/attribute/fillgraphicattribute.cxx | 6 | ||||
-rw-r--r-- | drawinglayer/source/primitive2d/sceneprimitive2d.cxx | 251 | ||||
-rw-r--r-- | drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx | 4 | ||||
-rw-r--r-- | drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx | 4 | ||||
-rw-r--r-- | drawinglayer/source/processor3d/zbufferprocessor3d.cxx | 394 | ||||
-rw-r--r-- | include/basegfx/matrix/b3dhommatrix.hxx | 2 | ||||
-rw-r--r-- | include/basegfx/polygon/b3dpolygon.hxx | 2 | ||||
-rw-r--r-- | include/basegfx/polygon/b3dpolypolygon.hxx | 2 | ||||
-rw-r--r-- | include/drawinglayer/processor3d/zbufferprocessor3d.hxx | 18 |
9 files changed, 376 insertions, 307 deletions
diff --git a/drawinglayer/source/attribute/fillgraphicattribute.cxx b/drawinglayer/source/attribute/fillgraphicattribute.cxx index 6d70e46de699..9465af23b054 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 27a4e0dc3943..68acb57ff5d6 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 a5fe0ddb0348..be15838fd8b7 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 be66c16d7a8b..f831aba427bd 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 0334c911ba76..3944f83705e0 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 b8e1c5b26c9c..ec8ee34f51d5 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 6c9c9b9c0808..d32968b47ac0 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 ea47e332f63b..9e3472dbb74c 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 8e3f6d4f3ac1..0f58a7f1f0ab 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; }; } } |