summaryrefslogtreecommitdiffstats
path: root/drawinglayer
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2016-04-29 12:30:16 +0200
committerArmin Le Grand <Armin.Le.Grand@cib.de>2016-05-06 10:11:03 +0000
commit657413b5deea11a850970f23cba2cf34a5bdf8ea (patch)
tree01d1daef3fe03fe7ad271e8efecaf189b94fe261 /drawinglayer
parenttdf#99426 Use correct path for lock in PUT method (diff)
downloadcore-657413b5deea11a850970f23cba2cf34a5bdf8ea.tar.gz
core-657413b5deea11a850970f23cba2cf34a5bdf8ea.zip
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>
Diffstat (limited to 'drawinglayer')
-rw-r--r--drawinglayer/source/attribute/fillgraphicattribute.cxx6
-rw-r--r--drawinglayer/source/primitive2d/sceneprimitive2d.cxx251
-rw-r--r--drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx4
-rw-r--r--drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx4
-rw-r--r--drawinglayer/source/processor3d/zbufferprocessor3d.cxx394
5 files changed, 363 insertions, 296 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