forked from mirrors/gecko-dev
		
	 575d8d016a
			
		
	
	
		575d8d016a
		
	
	
	
	
		
			
			So that accesses that use mSkipRect.XMost() - 4 or - 16 are aligned to a 4-byte boundary. Not doing so would crash on some architectures due to a SIGBUS. Differential Revision: https://phabricator.services.mozilla.com/D66748 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			198 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef MOZILLA_GFX_BLUR_H_
 | |
| #define MOZILLA_GFX_BLUR_H_
 | |
| 
 | |
| #include "mozilla/gfx/Rect.h"
 | |
| #include "mozilla/gfx/Point.h"
 | |
| #include "mozilla/CheckedInt.h"
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace gfx {
 | |
| 
 | |
| #ifdef _MSC_VER
 | |
| #  pragma warning(disable : 4251)
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * Implementation of a triple box blur approximation of a Gaussian blur.
 | |
|  *
 | |
|  * A Gaussian blur is good for blurring because, when done independently
 | |
|  * in the horizontal and vertical directions, it matches the result that
 | |
|  * would be obtained using a different (rotated) set of axes.  A triple
 | |
|  * box blur is a very close approximation of a Gaussian.
 | |
|  *
 | |
|  * This is a "service" class; the constructors set up all the information
 | |
|  * based on the values and compute the minimum size for an 8-bit alpha
 | |
|  * channel context.
 | |
|  * The callers are responsible for creating and managing the backing surface
 | |
|  * and passing the pointer to the data to the Blur() method.  This class does
 | |
|  * not retain the pointer to the data outside of the Blur() call.
 | |
|  *
 | |
|  * A spread N makes each output pixel the maximum value of all source
 | |
|  * pixels within a square of side length 2N+1 centered on the output pixel.
 | |
|  */
 | |
| class GFX2D_API AlphaBoxBlur final {
 | |
|  public:
 | |
|   /** Constructs a box blur and computes the backing surface size.
 | |
|    *
 | |
|    * @param aRect The coordinates of the surface to create in device units.
 | |
|    *
 | |
|    * @param aBlurRadius The blur radius in pixels.  This is the radius of the
 | |
|    *   entire (triple) kernel function.  Each individual box blur has radius
 | |
|    *   approximately 1/3 this value, or diameter approximately 2/3 this value.
 | |
|    *   This parameter should nearly always be computed using
 | |
|    * CalculateBlurRadius, below.
 | |
|    *
 | |
|    * @param aDirtyRect A pointer to a dirty rect, measured in device units, if
 | |
|    *   available.  This will be used for optimizing the blur operation. It is
 | |
|    *   safe to pass nullptr here.
 | |
|    *
 | |
|    * @param aSkipRect A pointer to a rect, measured in device units, that
 | |
|    *   represents an area where blurring is unnecessary and shouldn't be done
 | |
|    * for speed reasons. It is safe to pass nullptr here.
 | |
|    */
 | |
|   AlphaBoxBlur(const Rect& aRect, const IntSize& aSpreadRadius,
 | |
|                const IntSize& aBlurRadius, const Rect* aDirtyRect,
 | |
|                const Rect* aSkipRect);
 | |
| 
 | |
|   AlphaBoxBlur(const Rect& aRect, int32_t aStride, float aSigmaX,
 | |
|                float aSigmaY);
 | |
| 
 | |
|   AlphaBoxBlur();
 | |
| 
 | |
|   void Init(const Rect& aRect, const IntSize& aSpreadRadius,
 | |
|             const IntSize& aBlurRadius, const Rect* aDirtyRect,
 | |
|             const Rect* aSkipRect);
 | |
| 
 | |
|   ~AlphaBoxBlur();
 | |
| 
 | |
|   /**
 | |
|    * Return the size, in pixels, of the 8-bit alpha surface we'd use.
 | |
|    */
 | |
|   IntSize GetSize() const;
 | |
| 
 | |
|   /**
 | |
|    * Return the stride, in bytes, of the 8-bit alpha surface we'd use.
 | |
|    */
 | |
|   int32_t GetStride() const;
 | |
| 
 | |
|   /**
 | |
|    * Returns the device-space rectangle the 8-bit alpha surface covers.
 | |
|    */
 | |
|   IntRect GetRect() const;
 | |
| 
 | |
|   /**
 | |
|    * Return a pointer to a dirty rect, as passed in to the constructor, or
 | |
|    * nullptr if none was passed in.
 | |
|    */
 | |
|   Rect* GetDirtyRect();
 | |
| 
 | |
|   /**
 | |
|    * Return the spread radius, in pixels.
 | |
|    */
 | |
|   IntSize GetSpreadRadius() const { return mSpreadRadius; }
 | |
| 
 | |
|   /**
 | |
|    * Return the blur radius, in pixels.
 | |
|    */
 | |
|   IntSize GetBlurRadius() const { return mBlurRadius; }
 | |
| 
 | |
|   /**
 | |
|    * Return the minimum buffer size that should be given to Blur() method.  If
 | |
|    * zero, the class is not properly setup for blurring.  Note that this
 | |
|    * includes the extra three bytes on top of the stride*width, where something
 | |
|    * like gfxImageSurface::GetDataSize() would report without it, even if it
 | |
|    * happens to have the extra bytes.
 | |
|    */
 | |
|   size_t GetSurfaceAllocationSize() const;
 | |
| 
 | |
|   /**
 | |
|    * Perform the blur in-place on the surface backed by specified 8-bit
 | |
|    * alpha surface data. The size must be at least that returned by
 | |
|    * GetSurfaceAllocationSize() or bad things will happen.
 | |
|    */
 | |
|   void Blur(uint8_t* aData) const;
 | |
| 
 | |
|   /**
 | |
|    * Calculates a blur radius that, when used with box blur, approximates a
 | |
|    * Gaussian blur with the given standard deviation.  The result of this
 | |
|    * function should be used as the aBlurRadius parameter to AlphaBoxBlur's
 | |
|    * constructor, above.
 | |
|    */
 | |
|   static IntSize CalculateBlurRadius(const Point& aStandardDeviation);
 | |
|   static Float CalculateBlurSigma(int32_t aBlurRadius);
 | |
| 
 | |
|  private:
 | |
|   void BoxBlur_C(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe,
 | |
|                  int32_t aTopLobe, int32_t aBottomLobe,
 | |
|                  uint32_t* aIntegralImage, size_t aIntegralImageStride) const;
 | |
|   void BoxBlur_SSE2(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe,
 | |
|                     int32_t aTopLobe, int32_t aBottomLobe,
 | |
|                     uint32_t* aIntegralImage,
 | |
|                     size_t aIntegralImageStride) const;
 | |
|   void BoxBlur_NEON(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe,
 | |
|                     int32_t aTopLobe, int32_t aBottomLobe,
 | |
|                     uint32_t* aIntegralImage,
 | |
|                     size_t aIntegralImageStride) const;
 | |
| #ifdef _MIPS_ARCH_LOONGSON3A
 | |
|   void BoxBlur_LS3(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe,
 | |
|                    int32_t aTopLobe, int32_t aBottomLobe,
 | |
|                    uint32_t* aIntegralImage, size_t aIntegralImageStride) const;
 | |
| #endif
 | |
| 
 | |
|   static CheckedInt<int32_t> RoundUpToMultipleOf4(int32_t aVal);
 | |
| 
 | |
|   /**
 | |
|    * A rect indicating the area where blurring is unnecessary, and the blur
 | |
|    * algorithm should skip over it.
 | |
|    *
 | |
|    * This is guaranteed to be 4-pixel aligned in the x axis.
 | |
|    */
 | |
|   IntRect mSkipRect;
 | |
| 
 | |
|   /**
 | |
|    * The device-space rectangle the the backing 8-bit alpha surface covers.
 | |
|    */
 | |
|   IntRect mRect;
 | |
| 
 | |
|   /**
 | |
|    * A copy of the dirty rect passed to the constructor. This will only be valid
 | |
|    * if mHasDirtyRect is true.
 | |
|    */
 | |
|   Rect mDirtyRect;
 | |
| 
 | |
|   /**
 | |
|    * The spread radius, in pixels.
 | |
|    */
 | |
|   IntSize mSpreadRadius;
 | |
| 
 | |
|   /**
 | |
|    * The blur radius, in pixels.
 | |
|    */
 | |
|   IntSize mBlurRadius;
 | |
| 
 | |
|   /**
 | |
|    * The stride of the data passed to Blur()
 | |
|    */
 | |
|   int32_t mStride;
 | |
| 
 | |
|   /**
 | |
|    * The minimum size of the buffer needed for the Blur() operation.
 | |
|    */
 | |
|   size_t mSurfaceAllocationSize;
 | |
| 
 | |
|   /**
 | |
|    * Whether mDirtyRect contains valid data.
 | |
|    */
 | |
|   bool mHasDirtyRect;
 | |
| };
 | |
| 
 | |
| }  // namespace gfx
 | |
| }  // namespace mozilla
 | |
| 
 | |
| #endif /* MOZILLA_GFX_BLUR_H_ */
 |